summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xapi/current.txt11
-rw-r--r--api/system-current.txt35
-rw-r--r--cmds/statsd/src/StatsLogProcessor.cpp8
-rw-r--r--cmds/statsd/src/StatsService.cpp11
-rw-r--r--cmds/statsd/src/StatsService.h6
-rw-r--r--cmds/statsd/src/atoms.proto134
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.cpp14
-rw-r--r--cmds/statsd/src/logd/LogEvent.cpp25
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.cpp2
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.h2
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.cpp2
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.h10
-rw-r--r--cmds/statsd/src/packages/UidMap.cpp75
-rw-r--r--cmds/statsd/src/packages/UidMap.h26
-rw-r--r--cmds/statsd/src/stats_log.proto12
-rw-r--r--cmds/statsd/src/statsd_config.proto4
-rw-r--r--cmds/statsd/tests/LogEntryMatcher_test.cpp18
-rw-r--r--cmds/statsd/tests/StatsLogProcessor_test.cpp6
-rw-r--r--cmds/statsd/tests/UidMap_test.cpp102
-rw-r--r--cmds/statsd/tests/e2e/Attribution_e2e_test.cpp8
-rw-r--r--cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp32
-rw-r--r--config/hiddenapi-light-greylist.txt23
-rw-r--r--core/java/android/app/AppOpsManager.java37
-rw-r--r--core/java/android/app/ApplicationPackageManager.java9
-rw-r--r--core/java/android/app/ContextImpl.java31
-rw-r--r--core/java/android/app/IActivityManager.aidl4
-rw-r--r--core/java/android/app/INotificationManager.aidl2
-rw-r--r--core/java/android/app/Notification.java33
-rw-r--r--core/java/android/content/Context.java44
-rw-r--r--core/java/android/content/ContextWrapper.java6
-rw-r--r--core/java/android/content/Intent.java81
-rw-r--r--core/java/android/content/MimeTypeFilter.java154
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl2
-rw-r--r--core/java/android/content/pm/PackageManager.java24
-rw-r--r--core/java/android/content/res/AssetManager.java18
-rw-r--r--core/java/android/hardware/biometrics/BiometricPrompt.java34
-rw-r--r--core/java/android/hardware/display/ColorDisplayManager.java35
-rw-r--r--core/java/android/hardware/location/ContextHubClient.java100
-rw-r--r--core/java/android/hardware/location/ContextHubManager.java87
-rw-r--r--core/java/android/hardware/location/IContextHubClient.aidl6
-rw-r--r--core/java/android/hardware/location/IContextHubService.aidl7
-rw-r--r--core/java/android/os/BatteryStats.java2
-rw-r--r--core/java/android/os/FileUtils.java1
-rw-r--r--core/java/android/os/IStatsManager.aidl9
-rw-r--r--core/java/android/os/ParcelFileDescriptor.java3
-rw-r--r--core/java/android/os/PowerManager.java24
-rw-r--r--core/java/android/os/StatsLogEventWrapper.java8
-rw-r--r--core/java/android/os/storage/StorageManager.java3
-rw-r--r--core/java/android/provider/DocumentsContract.java155
-rw-r--r--core/java/android/provider/DocumentsProvider.java77
-rw-r--r--core/java/android/provider/Settings.java107
-rw-r--r--core/java/android/rolecontrollerservice/IRoleControllerService.aidl2
-rw-r--r--core/java/android/rolecontrollerservice/RoleControllerService.java17
-rw-r--r--core/java/android/security/keymaster/ExportResult.java5
-rw-r--r--core/java/android/security/keymaster/KeyCharacteristics.java8
-rw-r--r--core/java/android/security/keymaster/KeymasterCertificateChain.java8
-rw-r--r--core/java/android/security/keymaster/OperationResult.java4
-rw-r--r--core/java/android/text/Layout.java16
-rw-r--r--core/java/android/view/DisplayListCanvas.java49
-rw-r--r--core/java/android/view/IWindow.aidl29
-rw-r--r--core/java/android/view/InputApplicationHandle.java (renamed from services/core/java/com/android/server/input/InputApplicationHandle.java)2
-rw-r--r--core/java/android/view/InputChannel.java21
-rw-r--r--core/java/android/view/InputWindowHandle.java (renamed from services/core/java/com/android/server/input/InputWindowHandle.java)8
-rw-r--r--core/java/android/view/NotificationHeaderView.java5
-rw-r--r--core/java/android/view/RenderNodeAnimator.java6
-rw-r--r--core/java/android/view/SurfaceControl.java9
-rw-r--r--core/java/android/view/View.java173
-rw-r--r--core/java/android/view/ViewRootImpl.java34
-rw-r--r--core/java/android/view/WindowInsets.java16
-rw-r--r--core/java/android/view/intelligence/IntelligenceManager.java29
-rw-r--r--core/java/android/view/textclassifier/ModelFileManager.java3
-rw-r--r--core/java/android/webkit/WebView.java5
-rw-r--r--core/java/android/webkit/WebViewProvider.java6
-rw-r--r--core/java/android/widget/AdapterView.java22
-rw-r--r--core/java/android/widget/AppSecurityPermissions.java589
-rw-r--r--core/java/android/widget/CompoundButton.java11
-rw-r--r--core/java/android/widget/RadioGroup.java12
-rw-r--r--core/java/android/widget/TextView.java55
-rw-r--r--core/java/com/android/internal/app/ColorDisplayController.java7
-rw-r--r--core/java/com/android/internal/content/FileSystemProvider.java51
-rw-r--r--core/java/com/android/internal/os/BatterySipper.java4
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java3
-rw-r--r--core/java/com/android/internal/view/BaseIWindow.java3
-rw-r--r--core/java/com/android/internal/widget/SubtitleView.java2
-rw-r--r--core/jni/android_hardware_input_InputApplicationHandle.cpp4
-rw-r--r--core/jni/android_hardware_input_InputWindowHandle.cpp60
-rw-r--r--core/jni/android_util_AssetManager.cpp87
-rw-r--r--core/jni/android_view_InputChannel.cpp22
-rw-r--r--core/jni/android_view_SurfaceControl.cpp15
-rw-r--r--core/jni/com_android_internal_os_ZygoteInit.cpp37
-rw-r--r--core/jni/fd_utils.cpp4
-rw-r--r--core/proto/android/server/location/enums.proto30
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--core/res/res/layout/notification_template_header.xml22
-rw-r--r--core/res/res/values-night/themes_device_defaults.xml3
-rw-r--r--core/res/res/values/colors_car.xml4
-rw-r--r--core/res/res/values/colors_device_defaults.xml3
-rw-r--r--core/res/res/values/config.xml4
-rw-r--r--core/res/res/values/dimens_car.xml18
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/res/res/values/themes_device_defaults.xml2
-rw-r--r--core/tests/coretests/src/android/provider/SettingsBackupTest.java1
-rw-r--r--core/tests/coretests/src/android/view/WindowInsetsTest.java50
-rw-r--r--core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java22
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java31
-rw-r--r--core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java4
-rw-r--r--data/etc/Android.mk8
-rw-r--r--data/etc/com.android.timezone.updater.xml22
-rw-r--r--data/etc/platform.xml1
-rw-r--r--data/etc/privapp-permissions-platform.xml2
-rw-r--r--graphics/java/android/graphics/RecordingCanvas.java6
-rw-r--r--keystore/java/android/security/KeyStore.java345
-rw-r--r--keystore/java/android/security/keystore/KeystoreResponse.java78
-rw-r--r--libs/androidfw/AssetManager.cpp2
-rw-r--r--libs/androidfw/include/androidfw/AssetManager.h6
-rw-r--r--libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp6
-rw-r--r--libs/hwui/renderthread/EglManager.cpp8
-rw-r--r--libs/hwui/renderthread/EglManager.h3
-rw-r--r--libs/hwui/tests/unit/RenderNodeTests.cpp2
-rw-r--r--libs/hwui/utils/Result.h54
-rw-r--r--libs/services/src/os/StatsLogEventWrapper.cpp3
-rw-r--r--location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java24
-rw-r--r--media/java/android/media/AudioPresentation.java18
-rw-r--r--media/java/android/media/MediaDrm.java30
-rw-r--r--media/java/android/media/MediaExtractor.java35
-rw-r--r--media/java/android/media/MediaFormat.java16
-rw-r--r--media/java/android/media/MediaPlayer2.java44
-rw-r--r--media/java/android/media/MediaPlayer2Impl.java185
-rw-r--r--media/java/android/media/MediaPlayer2Utils.java41
-rw-r--r--media/jni/android_media_MediaPlayer2.cpp12
-rw-r--r--native/graphics/jni/Android.bp1
-rw-r--r--packages/CaptivePortalLogin/AndroidManifest.xml3
-rw-r--r--packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml28
-rw-r--r--packages/CaptivePortalLogin/res/layout/ssl_warning.xml86
-rw-r--r--packages/CaptivePortalLogin/res/values-af/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-am/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-ar/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-bg/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-bn/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-ca/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-cs/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-da/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-de/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-el/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-en-rGB/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-en-rIN/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-es-rUS/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-es/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-et/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-fa/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-fi/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-fr/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-hi/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-hr/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-hu/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-in/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-it/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-iw/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-ja/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-ko/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-lt/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-lv/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-ms/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-nb/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-nl/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-pl/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-pt/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-ro/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-ru/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-sk/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-sl/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-sr/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-sv/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-sw/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-th/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-tl/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-tr/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-uk/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-vi/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values-zu/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/res/values/strings.xml12
-rw-r--r--packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java87
-rw-r--r--packages/ExtServices/src/android/ext/services/notification/Assistant.java5
-rw-r--r--packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java4
-rw-r--r--packages/SettingsLib/SettingsSpinner/res/values/styles.xml2
-rw-r--r--packages/SettingsLib/res/drawable/list_divider_dark.xml24
-rw-r--r--packages/SettingsLib/res/layout/preference_two_target_divider.xml2
-rw-r--r--packages/SettingsLib/res/values/colors.xml1
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java62
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml4
-rw-r--r--packages/SystemUI/res/drawable/ic_notification_block.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_notifications_alert.xml24
-rw-r--r--packages/SystemUI/res/drawable/ic_notifications_silence.xml28
-rw-r--r--packages/SystemUI/res/drawable/privacy_chip_bg.xml2
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_camera.xml31
-rw-r--r--packages/SystemUI/res/drawable/stat_sys_mic_none.xml30
-rw-r--r--packages/SystemUI/res/layout/ongoing_privacy_chip.xml16
-rw-r--r--packages/SystemUI/res/layout/ongoing_privacy_dialog_content.xml20
-rw-r--r--packages/SystemUI/res/layout/ongoing_privacy_dialog_item.xml53
-rw-r--r--packages/SystemUI/res/layout/qs_footer_impl.xml2
-rw-r--r--packages/SystemUI/res/layout/qs_tile_label.xml2
-rw-r--r--packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml5
-rw-r--r--packages/SystemUI/res/values-land/dimens.xml1
-rw-r--r--packages/SystemUI/res/values/dimens.xml23
-rw-r--r--packages/SystemUI/res/values/strings.xml39
-rw-r--r--packages/SystemUI/res/values/styles.xml26
-rw-r--r--packages/SystemUI/src/com/android/keyguard/CarrierText.java9
-rw-r--r--packages/SystemUI/src/com/android/keyguard/EmergencyButton.java3
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java12
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java3
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java3
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java9
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java19
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java9
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/DejankUtils.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/ExpandHelper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/ImageWallpaper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/LatencyTester.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/RegionInterceptingFrameLayout.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/ScreenDecorations.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/SwipeHelper.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/SysUIToast.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemBars.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIService.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipUI.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java10
-rwxr-xr-xpackages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt60
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt107
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt73
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/AlphaControlledSignalTileView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/CellTileView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFooter.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragment.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileColorPicker.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/touch/SwipeDetector.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Recents.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NeutralGoodDrawable.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconContainer.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java105
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java116
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java47
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/BetterListPreference.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/OtherPrefs.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerService.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java68
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt53
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java61
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java200
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java25
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java48
-rw-r--r--proto/src/metrics_constants/metrics_constants.proto8
-rw-r--r--proto/src/wifi.proto16
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerService.java31
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java686
-rw-r--r--services/backup/java/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunker.java136
-rw-r--r--services/backup/java/com/android/server/backup/encryption/chunking/cdc/FingerprintMixer.java95
-rw-r--r--services/backup/java/com/android/server/backup/encryption/chunking/cdc/Hkdf.java115
-rw-r--r--services/backup/java/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpoint.java78
-rw-r--r--services/backup/java/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64.java113
-rw-r--r--services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java4
-rw-r--r--services/core/Android.bp2
-rw-r--r--services/core/java/com/android/server/AbstractMasterSystemService.java20
-rw-r--r--services/core/java/com/android/server/AbstractPerUserSystemService.java16
-rw-r--r--services/core/java/com/android/server/AppOpsService.java66
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java5
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java215
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java91
-rw-r--r--services/core/java/com/android/server/am/AppBindRecord.java4
-rw-r--r--services/core/java/com/android/server/am/ConnectionRecord.java12
-rw-r--r--services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java128
-rw-r--r--services/core/java/com/android/server/am/IntentBindRecord.java2
-rw-r--r--services/core/java/com/android/server/am/OWNERS2
-rw-r--r--services/core/java/com/android/server/am/ServiceRecord.java17
-rw-r--r--services/core/java/com/android/server/am/SettingsToPropertiesMapper.java265
-rw-r--r--services/core/java/com/android/server/biometrics/BiometricService.java21
-rw-r--r--services/core/java/com/android/server/clipboard/ClipboardService.java21
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java38
-rw-r--r--services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java33
-rw-r--r--services/core/java/com/android/server/location/ContextHubClientBroker.java186
-rw-r--r--services/core/java/com/android/server/location/ContextHubClientManager.java103
-rw-r--r--services/core/java/com/android/server/location/ContextHubService.java30
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java36
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecord.java20
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java142
-rw-r--r--services/core/java/com/android/server/om/IdmapManager.java94
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerSettings.java6
-rw-r--r--services/core/java/com/android/server/pm/LauncherAppsService.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java21
-rw-r--r--services/core/java/com/android/server/pm/Settings.java5
-rw-r--r--services/core/java/com/android/server/pm/SharedUserSetting.java5
-rw-r--r--services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java2
-rw-r--r--services/core/java/com/android/server/role/RemoteRoleControllerService.java83
-rw-r--r--services/core/java/com/android/server/role/RoleManagerService.java30
-rw-r--r--services/core/java/com/android/server/stats/StatsCompanionService.java135
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java15
-rw-r--r--services/core/java/com/android/server/wm/ActivityMetricsLogger.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java48
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java9
-rw-r--r--services/core/java/com/android/server/wm/AppWindowContainerController.java17
-rw-r--r--services/core/java/com/android/server/wm/AppWindowContainerListener.java4
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java10
-rw-r--r--services/core/java/com/android/server/wm/Dimmer.java5
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java46
-rw-r--r--services/core/java/com/android/server/wm/DragDropController.java2
-rw-r--r--services/core/java/com/android/server/wm/DragState.java6
-rw-r--r--services/core/java/com/android/server/wm/InputConsumerImpl.java6
-rw-r--r--services/core/java/com/android/server/wm/InputManagerCallback.java27
-rw-r--r--services/core/java/com/android/server/wm/InputMonitor.java7
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimationController.java2
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java34
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioner.java7
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioningController.java2
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java41
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java23
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp92
-rw-r--r--services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java24
-rw-r--r--services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java31
-rw-r--r--services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java46
-rw-r--r--services/java/com/android/server/SystemServer.java145
-rw-r--r--services/robotests/Android.mk3
-rw-r--r--services/robotests/src/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunkerTest.java232
-rw-r--r--services/robotests/src/com/android/server/backup/encryption/chunking/cdc/FingerprintMixerTest.java205
-rw-r--r--services/robotests/src/com/android/server/backup/encryption/chunking/cdc/HkdfTest.java95
-rw-r--r--services/robotests/src/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpointTest.java122
-rw-r--r--services/robotests/src/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64Test.java132
-rw-r--r--services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java115
-rw-r--r--services/tests/servicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java211
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/DimmerTests.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java37
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/TestIWindow.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java12
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java2
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java6
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java155
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java22
-rw-r--r--services/usage/java/com/android/server/usage/UserUsageStatsService.java6
-rw-r--r--startop/view_compiler/dex_builder.cc104
-rw-r--r--startop/view_compiler/dex_builder.h111
-rw-r--r--startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java42
-rw-r--r--startop/view_compiler/dex_testcase_generator.cc78
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java15
-rw-r--r--telephony/java/android/telephony/CellConfigLte.java105
-rw-r--r--telephony/java/android/telephony/CellInfoLte.java42
-rw-r--r--telephony/java/android/telephony/DataSpecificRegistrationStates.java43
-rw-r--r--telephony/java/android/telephony/NetworkRegistrationState.java111
-rw-r--r--telephony/java/android/telephony/PhoneStateListener.java347
-rw-r--r--telephony/java/android/telephony/ServiceState.java70
-rw-r--r--telephony/java/android/telephony/SubscriptionInfo.java40
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java51
-rw-r--r--telephony/java/android/telephony/ims/ImsMmTelManager.java2
-rw-r--r--telephony/java/android/telephony/ims/ProvisioningManager.java252
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java68
-rw-r--r--telephony/java/com/android/ims/ImsConfig.java43
-rwxr-xr-xtelephony/java/com/android/internal/telephony/ISub.aidl20
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl39
-rw-r--r--test-mock/api/current.txt1
-rw-r--r--test-mock/src/android/test/mock/MockContext.java7
-rw-r--r--test-runner/src/android/test/IsolatedContext.java6
-rw-r--r--tools/aapt2/Debug.cpp4
-rw-r--r--tools/aapt2/ResourceUtils.cpp4
-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.cpp182
-rw-r--r--tools/aapt2/cmd/Convert.h6
-rw-r--r--tools/aapt2/format/binary/TableFlattener.cpp20
-rw-r--r--tools/aapt2/format/binary/TableFlattener.h3
-rw-r--r--wifi/java/android/net/wifi/IWifiManager.aidl4
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java6
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java40
-rw-r--r--wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java42
-rw-r--r--wifi/java/android/net/wifi/hotspot2/pps/Credential.java24
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pManager.java66
-rw-r--r--wifi/java/com/android/server/wifi/AbstractWifiService.java23
-rw-r--r--wifi/tests/src/android/net/wifi/WifiConfigurationTest.java30
-rw-r--r--wifi/tests/src/android/net/wifi/WifiManagerTest.java38
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java40
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java138
617 files changed, 10656 insertions, 4557 deletions
diff --git a/api/current.txt b/api/current.txt
index f22856c58fbe..42758c87ade5 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -5370,6 +5370,7 @@ package android.app {
field public static final android.os.Parcelable.Creator<android.app.Notification.Action> CREATOR;
field public static final int SEMANTIC_ACTION_ARCHIVE = 5; // 0x5
field public static final int SEMANTIC_ACTION_CALL = 10; // 0xa
+ field public static final int SEMANTIC_ACTION_CONTEXTUAL_SUGGESTION = 11; // 0xb
field public static final int SEMANTIC_ACTION_DELETE = 4; // 0x4
field public static final int SEMANTIC_ACTION_MARK_AS_READ = 2; // 0x2
field public static final int SEMANTIC_ACTION_MARK_AS_UNREAD = 3; // 0x3
@@ -9475,6 +9476,7 @@ package android.content {
public abstract class Context {
ctor public Context();
+ method public abstract boolean bindIsolatedService(android.content.Intent, android.content.ServiceConnection, int, java.lang.String);
method public abstract boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
method public abstract int checkCallingOrSelfPermission(java.lang.String);
method public abstract int checkCallingOrSelfUriPermission(android.net.Uri, int);
@@ -9686,6 +9688,7 @@ package android.content {
public class ContextWrapper extends android.content.Context {
ctor public ContextWrapper(android.content.Context);
method protected void attachBaseContext(android.content.Context);
+ method public boolean bindIsolatedService(android.content.Intent, android.content.ServiceConnection, int, java.lang.String);
method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
method public int checkCallingOrSelfPermission(java.lang.String);
method public int checkCallingOrSelfUriPermission(android.net.Uri, int);
@@ -24462,6 +24465,7 @@ package android.media {
}
public static final class MediaExtractor.CasInfo {
+ method public byte[] getPrivateData();
method public android.media.MediaCas.Session getSession();
method public int getSystemId();
}
@@ -28998,11 +29002,14 @@ package android.net.wifi {
method public boolean is5GHzBandSupported();
method public boolean isDeviceToApRttSupported();
method public boolean isEnhancedPowerReportingSupported();
+ method public boolean isOweSupported();
method public boolean isP2pSupported();
method public boolean isPreferredNetworkOffloadSupported();
method public deprecated boolean isScanAlwaysAvailable();
method public boolean isTdlsSupported();
method public boolean isWifiEnabled();
+ method public boolean isWpa3SaeSupported();
+ method public boolean isWpa3SuiteBSupported();
method public deprecated boolean pingSupplicant();
method public deprecated boolean reassociate();
method public deprecated boolean reconnect();
@@ -43324,6 +43331,7 @@ package android.telephony {
public class PhoneStateListener {
ctor public PhoneStateListener();
+ ctor public PhoneStateListener(java.util.concurrent.Executor);
method public void onCallForwardingIndicatorChanged(boolean);
method public void onCallStateChanged(int, java.lang.String);
method public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>);
@@ -43549,6 +43557,7 @@ package android.telephony {
method public java.lang.String getCountryIso();
method public int getDataRoaming();
method public java.lang.CharSequence getDisplayName();
+ method public java.lang.String getGroupUuid();
method public java.lang.String getIccId();
method public int getIconTint();
method public deprecated int getMcc();
@@ -43556,7 +43565,6 @@ package android.telephony {
method public deprecated int getMnc();
method public java.lang.String getMncString();
method public java.lang.String getNumber();
- method public int getParentSubId();
method public int getSimSlotIndex();
method public int getSubscriptionId();
method public boolean isEmbedded();
@@ -43590,6 +43598,7 @@ package android.telephony {
method public static boolean isValidSubscriptionId(int);
method public void removeOnOpportunisticSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
+ method public java.lang.String setSubscriptionGroup(int[]);
method public void setSubscriptionOverrideCongested(int, boolean, long);
method public void setSubscriptionOverrideUnmetered(int, boolean, long);
method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>);
diff --git a/api/system-current.txt b/api/system-current.txt
index 5c4efcd90b5b..4524e752a1bd 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -137,6 +137,7 @@ package android {
field public static final java.lang.String PROVIDE_RESOLVER_RANKER_SERVICE = "android.permission.PROVIDE_RESOLVER_RANKER_SERVICE";
field public static final java.lang.String PROVIDE_TRUST_AGENT = "android.permission.PROVIDE_TRUST_AGENT";
field public static final java.lang.String QUERY_TIME_ZONE_RULES = "android.permission.QUERY_TIME_ZONE_RULES";
+ field public static final java.lang.String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
field public static final java.lang.String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS";
field public static final java.lang.String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE";
field public static final java.lang.String READ_INSTALL_SESSIONS = "android.permission.READ_INSTALL_SESSIONS";
@@ -1205,6 +1206,7 @@ package android.content.pm {
public abstract class PackageManager {
method public abstract void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
method public abstract boolean arePermissionsIndividuallyControlled();
+ method public boolean canSuspendPackage(java.lang.String);
method public abstract java.util.List<android.content.IntentFilter> getAllIntentFilters(java.lang.String);
method public android.content.pm.dex.ArtManager getArtManager();
method public abstract java.lang.String getDefaultBrowserPackageNameAsUser(int);
@@ -3639,17 +3641,15 @@ package android.net.wifi {
public class WifiManager {
method public void connect(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
+ method public java.util.List<android.net.wifi.WifiConfiguration> getAllMatchingWifiConfigs(java.util.List<android.net.wifi.ScanResult>);
method public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
method public android.net.wifi.WifiConfiguration getWifiApConfiguration();
method public int getWifiApState();
method public boolean isDeviceToApRttSupported();
method public boolean isDeviceToDeviceRttSupported();
- method public boolean isOweSupported();
method public boolean isPortableHotspotSupported();
method public boolean isWifiApEnabled();
method public boolean isWifiScannerSupported();
- method public boolean isWpa3SaeSupported();
- method public boolean isWpa3SuiteBSupported();
method public void registerNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback, android.os.Handler);
method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
method public boolean startScan(android.os.WorkSource);
@@ -4109,6 +4109,7 @@ package android.os {
}
public final class PowerManager {
+ method public void dream(long);
method public int getPowerSaveMode();
method public boolean setDynamicPowerSavings(boolean, int);
method public boolean setPowerSaveMode(boolean);
@@ -4545,10 +4546,6 @@ package android.provider {
public final class Settings {
field public static final java.lang.String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS";
field public static final java.lang.String ACTION_SHOW_ADMIN_SUPPORT_DETAILS = "android.settings.SHOW_ADMIN_SUPPORT_DETAILS";
- field public static final int USER_SETUP_PERSONALIZATION_COMPLETE = 10; // 0xa
- field public static final int USER_SETUP_PERSONALIZATION_NOT_STARTED = 0; // 0x0
- field public static final int USER_SETUP_PERSONALIZATION_PAUSED = 2; // 0x2
- field public static final int USER_SETUP_PERSONALIZATION_STARTED = 1; // 0x1
}
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
@@ -4592,6 +4589,10 @@ package android.provider {
field public static final java.lang.String LOCK_SCREEN_SHOW_NOTIFICATIONS = "lock_screen_show_notifications";
field public static final java.lang.String MANUAL_RINGER_TOGGLE_COUNT = "manual_ringer_toggle_count";
field public static final java.lang.String USER_SETUP_COMPLETE = "user_setup_complete";
+ field public static final int USER_SETUP_PERSONALIZATION_COMPLETE = 10; // 0xa
+ field public static final int USER_SETUP_PERSONALIZATION_NOT_STARTED = 0; // 0x0
+ field public static final int USER_SETUP_PERSONALIZATION_PAUSED = 2; // 0x2
+ field public static final int USER_SETUP_PERSONALIZATION_STARTED = 1; // 0x1
field public static final java.lang.String USER_SETUP_PERSONALIZATION_STATE = "user_setup_personalization_state";
field public static final java.lang.String VOLUME_HUSH_GESTURE = "volume_hush_gesture";
}
@@ -5461,6 +5462,7 @@ package android.telephony {
method public static android.os.PersistableBundle getDefaultConfig();
method public void overrideConfig(int, android.os.PersistableBundle);
method public void updateConfigForPhoneId(int, java.lang.String);
+ field public static final java.lang.String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string";
field public static final java.lang.String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING = "config_plans_package_override_string";
}
@@ -5535,8 +5537,10 @@ package android.telephony {
public class PhoneStateListener {
method public void onRadioPowerStateChanged(int);
method public void onSrvccStateChanged(int);
+ method public void onVoiceActivationStateChanged(int);
field public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000
field public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000
+ field public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000
}
public class ServiceState implements android.os.Parcelable {
@@ -6600,6 +6604,22 @@ package android.telephony.ims {
method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile);
}
+ public class ProvisioningManager {
+ method public static android.telephony.ims.ProvisioningManager createForSubscriptionId(android.content.Context, int);
+ method public int getProvisioningIntValue(int);
+ method public java.lang.String getProvisioningStringValue(int);
+ method public void registerProvisioningChangedCallback(java.util.concurrent.Executor, android.telephony.ims.ProvisioningManager.Callback);
+ method public int setProvisioningIntValue(int, int);
+ method public int setProvisioningStringValue(int, java.lang.String);
+ method public void unregisterProvisioningChangedCallback(android.telephony.ims.ProvisioningManager.Callback);
+ }
+
+ public static class ProvisioningManager.Callback {
+ ctor public ProvisioningManager.Callback();
+ method public void onProvisioningIntChanged(int, int);
+ method public void onProvisioningStringChanged(int, java.lang.String);
+ }
+
}
package android.telephony.ims.feature {
@@ -7410,6 +7430,7 @@ package android.webkit {
method public default void onMovedToDisplay(int, android.content.res.Configuration);
method public abstract void onOverScrolled(int, int, boolean, boolean);
method public default void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
+ method public default boolean onProvideContentCaptureStructure(android.view.ViewStructure, int);
method public abstract void onProvideVirtualStructure(android.view.ViewStructure);
method public abstract void onScrollChanged(int, int, int, int);
method public abstract void onSizeChanged(int, int, int, int);
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index eb498f596141..a9819972cfc7 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -370,11 +370,9 @@ void StatsLogProcessor::onConfigMetricsReportLocked(const ConfigKey& key,
// This skips the uid map if it's an empty config.
if (it->second->getNumMetrics() > 0) {
uint64_t uidMapToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP);
- if (it->second->hashStringInReport()) {
- mUidMap->appendUidMap(dumpTimeStampNs, key, &str_set, proto);
- } else {
- mUidMap->appendUidMap(dumpTimeStampNs, key, nullptr, proto);
- }
+ mUidMap->appendUidMap(
+ dumpTimeStampNs, key, it->second->hashStringInReport() ? &str_set : nullptr,
+ it->second->versionStringsInReport(), it->second->installerInReport(), proto);
proto->end(uidMapToken);
}
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 27685fc108a0..7fa05be29b9d 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -787,21 +787,24 @@ status_t StatsService::cmd_print_logs(int out, const Vector<String8>& args) {
}
Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version,
- const vector<String16>& app) {
+ const vector<String16>& version_string,
+ const vector<String16>& app,
+ const vector<String16>& installer) {
ENFORCE_UID(AID_SYSTEM);
VLOG("StatsService::informAllUidData was called");
- mUidMap->updateMap(getElapsedRealtimeNs(), uid, version, app);
+ mUidMap->updateMap(getElapsedRealtimeNs(), uid, version, version_string, app, installer);
VLOG("StatsService::informAllUidData succeeded");
return Status::ok();
}
-Status StatsService::informOnePackage(const String16& app, int32_t uid, int64_t version) {
+Status StatsService::informOnePackage(const String16& app, int32_t uid, int64_t version,
+ const String16& version_string, const String16& installer) {
ENFORCE_UID(AID_SYSTEM);
VLOG("StatsService::informOnePackage was called");
- mUidMap->updateApp(getElapsedRealtimeNs(), app, uid, version);
+ mUidMap->updateApp(getElapsedRealtimeNs(), app, uid, version, version_string, installer);
return Status::ok();
}
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 4a5f05fef034..cd4d601a606f 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -73,8 +73,10 @@ public:
virtual Status informAlarmForSubscriberTriggeringFired();
virtual Status informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version,
- const vector<String16>& app);
- virtual Status informOnePackage(const String16& app, int32_t uid, int64_t version);
+ const vector<String16>& version_string,
+ const vector<String16>& app, const vector<String16>& installer);
+ virtual Status informOnePackage(const String16& app, int32_t uid, int64_t version,
+ const String16& version_string, const String16& installer);
virtual Status informOnePackageRemoved(const String16& app, int32_t uid);
virtual Status informDeviceShutdown();
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 21e7203ffa88..5ca5aa386d52 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -27,6 +27,7 @@ import "frameworks/base/core/proto/android/app/job/enums.proto";
import "frameworks/base/core/proto/android/bluetooth/enums.proto";
import "frameworks/base/core/proto/android/os/enums.proto";
import "frameworks/base/core/proto/android/server/enums.proto";
+import "frameworks/base/core/proto/android/server/location/enums.proto";
import "frameworks/base/core/proto/android/service/procstats_enum.proto";
import "frameworks/base/core/proto/android/stats/enums.proto";
import "frameworks/base/core/proto/android/stats/launcher/launcher.proto";
@@ -118,7 +119,7 @@ message Atom {
ResourceConfigurationChanged resource_configuration_changed = 66;
BluetoothEnabledStateChanged bluetooth_enabled_state_changed = 67;
BluetoothConnectionStateChanged bluetooth_connection_state_changed = 68;
- // 69 is blank but need not be.
+ GpsSignalQualityChanged gps_signal_quality_changed = 69;
UsbConnectorStateChanged usb_connector_state_changed = 70;
SpeakerImpedanceReported speaker_impedance_reported = 71;
HardwareFailed hardware_failed = 72;
@@ -147,6 +148,12 @@ message Atom {
PhoneStateChanged phone_state_changed = 95;
UserRestrictionChanged user_restriction_changed = 96;
SettingsUIChanged settings_ui_changed = 97;
+ ConnectivityStateChanged connectivity_state_changed = 98;
+ // TODO: service state change is very noisy shortly after boot, as well
+ // as at other transitions - coming out of doze, device plugged in, etc.
+ // Consider removing this if it becomes a problem
+ ServiceStateChanged service_state_changed = 99;
+ ServiceLaunchReported service_launch_reported = 100;
}
// Pulled events will start at field 10000.
@@ -191,6 +198,9 @@ message Atom {
NativeProcessMemoryState native_process_memory_state = 10036;
CpuTimePerThreadFreq cpu_time_per_thread_freq = 10037;
OnDevicePowerMeasurement on_device_power_measurement = 10038;
+ DeviceCalculatedPowerUse device_calculated_power_use = 10039;
+ DeviceCalculatedPowerBlameUid device_calculated_power_blame_uid = 10040;
+ DeviceCalculatedPowerBlameOther device_calculated_power_blame_other = 10041;
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -485,7 +495,6 @@ message SensorStateChanged {
optional State state = 3;
}
-
/**
* Logs when GPS state changes.
*
@@ -502,6 +511,16 @@ message GpsScanStateChanged {
optional State state = 2;
}
+/**
+ * Logs when GPS signal quality.
+ *
+ * Logged from:
+ * /frameworks/base/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+ */
+message GpsSignalQualityChanged {
+ optional android.server.location.GpsSignalQualityEnum level = 1;
+}
+
/**
* Logs when a sync manager sync state changes.
@@ -2129,6 +2148,57 @@ message Notification {
optional int64 visible_millis = 16;
}
+/*
+ * Logs when a connection becomes available and lost.
+ * Logged in StatsCompanionService.java
+ */
+message ConnectivityStateChanged {
+ // Id of the network.
+ optional int32 net_id = 1;
+
+ enum State {
+ UNKNOWN = 0;
+ CONNECTED = 1;
+ DISCONNECTED = 2;
+ }
+ // Connected state of a network.
+ optional State state = 2;
+}
+
+/**
+ * Logs when a service starts and stops.
+ * Logged from:
+ * services/core/java/com/android/server/am/ActiveServices.java
+ */
+message ServiceStateChanged {
+
+ optional int32 uid = 1 [(is_uid) = true];
+
+ optional string package_name = 2;
+
+ optional string service_name = 3;
+
+ enum State {
+ START = 1;
+ STOP = 2;
+ }
+
+ optional State state = 4;
+}
+
+/**
+ * Logs when a service is launched.
+ * Logged from:
+ * services/core/java/com/android/server/am/ActiveServices.java
+ */
+message ServiceLaunchReported {
+
+ optional int32 uid = 1 [(is_uid) = true];
+
+ optional string package_name = 2;
+
+ optional string service_name = 3;
+}
//////////////////////////////////////////////////////////////////////
// Pulled atoms below this line //
@@ -3181,3 +3251,63 @@ message CpuTimePerThreadFreq {
// Time spent in frequency in milliseconds, since thread start.
optional uint32 time_millis = 7;
}
+
+/**
+ * Pulls on-device BatteryStats power use calculations for the overall device.
+ */
+message DeviceCalculatedPowerUse {
+ // Power used by the device in mAh, as computed by BatteryStats, since BatteryStats last reset
+ // (i.e. roughly since device was last significantly charged).
+ // Currently, this is BatteryStatsHelper.getComputedPower() (not getTotalPower()).
+ optional float computed_power_milli_amp_hours = 1;
+}
+
+/**
+ * Pulls on-device BatteryStats power use calculations broken down by uid.
+ * This atom should be complemented by DeviceCalculatedPowerBlameOther, which contains the power use
+ * that is attributed to non-uid items. They must all be included to get the total power use.
+ */
+message DeviceCalculatedPowerBlameUid {
+ // Uid being blamed. Note: isolated uids have already been mapped to host uid.
+ optional int32 uid = 1 [(is_uid) = true];
+
+ // Power used by this uid in mAh, as computed by BatteryStats, since BatteryStats last reset
+ // (i.e. roughly since device was last significantly charged).
+ optional float power_milli_amp_hours = 2;
+}
+
+/**
+ * Pulls on-device BatteryStats power use calculations that are not due to a uid, broken down by
+ * drain type.
+ * This atom should be complemented by DeviceCalculatedPowerBlameUid, which contains the blame that
+ * is attributed uids. They must all be included to get the total power use.
+ */
+message DeviceCalculatedPowerBlameOther {
+ // The type of item whose power use is being reported.
+ enum DrainType {
+ AMBIENT_DISPLAY = 0;
+ // reserved 1; reserved "APP"; // Logged instead in DeviceCalculatedPowerBlameUid.
+ BLUETOOTH = 2;
+ CAMERA = 3;
+ // Cell-standby
+ CELL = 4;
+ FLASHLIGHT = 5;
+ IDLE = 6;
+ MEMORY = 7;
+ // Amount that total computed drain exceeded the drain estimated using the
+ // battery level changes and capacity.
+ OVERCOUNTED = 8;
+ PHONE = 9;
+ SCREEN = 10;
+ // Amount that total computed drain was below the drain estimated using the
+ // battery level changes and capacity.
+ UNACCOUNTED = 11;
+ // reserved 12; reserved "USER"; // Entire drain for a user. This is NOT supported.
+ WIFI = 13;
+ }
+ optional DrainType drain_type = 1;
+
+ // Power used by this item in mAh, as computed by BatteryStats, since BatteryStats last reset
+ // (i.e. roughly since device was last significantly charged).
+ optional float power_milli_amp_hours = 2;
+} \ No newline at end of file
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 8378ae15c1ef..0e131cb6c8c9 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -243,6 +243,20 @@ const std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
{2, 3, 4, 5, 6},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::CPU_TIME_PER_THREAD_FREQ)}},
+ // DeviceCalculatedPowerUse.
+ {android::util::DEVICE_CALCULATED_POWER_USE,
+ {{}, {}, 1 * NS_PER_SEC,
+ new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_USE)}},
+ // DeviceCalculatedPowerBlameUid.
+ {android::util::DEVICE_CALCULATED_POWER_BLAME_UID,
+ {{}, {}, // BatteryStats already merged isolated with host ids so it's unnecessary here.
+ 1 * NS_PER_SEC,
+ new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_BLAME_UID)}},
+ // DeviceCalculatedPowerBlameOther.
+ {android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER,
+ {{}, {},
+ 1 * NS_PER_SEC,
+ new StatsCompanionServicePuller(android::util::DEVICE_CALCULATED_POWER_BLAME_OTHER)}},
};
StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index febb9229bc95..625294ce5e49 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -156,9 +156,6 @@ LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
FieldValue(Field(mTagId, getSimpleField(1)), Value(speakerImpedance.speakerLocation)));
mValues.push_back(
FieldValue(Field(mTagId, getSimpleField(2)), Value(speakerImpedance.milliOhms)));
- if (!mValues.empty()) {
- mValues.back().mField.decorateLastPos(1);
- }
}
LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
@@ -173,9 +170,6 @@ LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
FieldValue(Field(mTagId, getSimpleField(2)), Value(hardwareFailed.hardwareLocation)));
mValues.push_back(
FieldValue(Field(mTagId, getSimpleField(3)), Value(int32_t(hardwareFailed.errorCode))));
- if (!mValues.empty()) {
- mValues.back().mField.decorateLastPos(1);
- }
}
LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
@@ -190,9 +184,6 @@ LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
FieldValue(Field(mTagId, getSimpleField(2)), Value(physicalDropDetected.accelPeak)));
mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)),
Value(physicalDropDetected.freefallDuration)));
- if (!mValues.empty()) {
- mValues.back().mField.decorateLastPos(1);
- }
}
LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
@@ -205,10 +196,6 @@ LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
mValues.push_back(FieldValue(Field(mTagId, getSimpleField(i + 1)),
Value(chargeCycles.cycleBucket[i])));
}
-
- if (!mValues.empty()) {
- mValues.back().mField.decorateLastPos(1);
- }
}
LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
@@ -231,10 +218,6 @@ LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
Value(batteryHealthSnapshotArgs.resistanceMicroOhm)));
mValues.push_back(FieldValue(Field(mTagId, getSimpleField(7)),
Value(batteryHealthSnapshotArgs.levelPercent)));
-
- if (!mValues.empty()) {
- mValues.back().mField.decorateLastPos(1);
- }
}
LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs, const SlowIo& slowIo) {
@@ -247,10 +230,6 @@ LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs, con
FieldValue(Field(mTagId, getSimpleField(1)), Value(int32_t(slowIo.operation))));
pos[0]++;
mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(slowIo.count)));
-
- if (!mValues.empty()) {
- mValues.back().mField.decorateLastPos(1);
- }
}
LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
@@ -261,10 +240,6 @@ LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
mValues.push_back(FieldValue(Field(mTagId, getSimpleField(1)),
Value(batteryCausedShutdown.voltageMicroV)));
-
- if (!mValues.empty()) {
- mValues.back().mField.decorateLastPos(1);
- }
}
LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) : LogEvent(tagId, timestampNs, 0) {}
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 05103a962c33..461ad28dc77f 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -140,7 +140,7 @@ GaugeMetricProducer::GaugeMetricProducer(const ConfigKey& key, const GaugeMetric
// Adjust start for partial bucket
mCurrentBucketStartTimeNs = startTimeNs;
- if (mIsPulled) {
+ if (mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
pullAndMatchEventsLocked(startTimeNs);
}
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h
index 5866139047ae..6e3530b0daf4 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.h
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h
@@ -80,7 +80,7 @@ public:
}
flushCurrentBucketLocked(eventTimeNs);
mCurrentBucketStartTimeNs = eventTimeNs;
- if (mIsPulled) {
+ if (mIsPulled && mSamplingType == GaugeMetric::RANDOM_ONE_SAMPLE) {
pullAndMatchEventsLocked(eventTimeNs);
}
};
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 4244d5bed23b..ac34f4760a12 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -77,6 +77,8 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
mActivationAtomTrackerToMetricMap, mMetricIndexesWithActivation, mNoReportMetricIds);
mHashStringsInReport = config.hash_strings_in_metric_report();
+ mVersionStringsInReport = config.version_strings_in_metric_report();
+ mInstallerInReport = config.installer_in_metric_report();
if (config.allowed_log_source_size() == 0) {
mConfigValid = false;
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index a4672b68f2bc..a31efbd3c8a6 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -83,6 +83,14 @@ public:
return mHashStringsInReport;
};
+ inline bool versionStringsInReport() const {
+ return mVersionStringsInReport;
+ };
+
+ inline bool installerInReport() const {
+ return mInstallerInReport;
+ };
+
void refreshTtl(const int64_t currentTimestampNs) {
if (mTtlNs > 0) {
mTtlEndNs = currentTimestampNs + mTtlNs;
@@ -126,6 +134,8 @@ private:
bool mConfigValid = false;
bool mHashStringsInReport = false;
+ bool mVersionStringsInReport = false;
+ bool mInstallerInReport = false;
const int64_t mTtlNs;
int64_t mTtlEndNs;
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index 37a00673959c..59f3f0448e0e 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -49,6 +49,10 @@ const int FIELD_ID_SNAPSHOT_PACKAGE_VERSION = 2;
const int FIELD_ID_SNAPSHOT_PACKAGE_UID = 3;
const int FIELD_ID_SNAPSHOT_PACKAGE_DELETED = 4;
const int FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH = 5;
+const int FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING = 6;
+const int FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING_HASH = 7;
+const int FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER = 8;
+const int FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER_HASH = 9;
const int FIELD_ID_SNAPSHOT_TIMESTAMP = 1;
const int FIELD_ID_SNAPSHOT_PACKAGE_INFO = 2;
const int FIELD_ID_SNAPSHOTS = 1;
@@ -60,6 +64,10 @@ const int FIELD_ID_CHANGE_UID = 4;
const int FIELD_ID_CHANGE_NEW_VERSION = 5;
const int FIELD_ID_CHANGE_PREV_VERSION = 6;
const int FIELD_ID_CHANGE_PACKAGE_HASH = 7;
+const int FIELD_ID_CHANGE_NEW_VERSION_STRING = 8;
+const int FIELD_ID_CHANGE_PREV_VERSION_STRING = 9;
+const int FIELD_ID_CHANGE_NEW_VERSION_STRING_HASH = 10;
+const int FIELD_ID_CHANGE_PREV_VERSION_STRING_HASH = 11;
UidMap::UidMap() : mBytesUsed(0) {}
@@ -104,7 +112,8 @@ int64_t UidMap::getAppVersion(int uid, const string& packageName) const {
}
void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
- const vector<int64_t>& versionCode, const vector<String16>& packageName) {
+ const vector<int64_t>& versionCode, const vector<String16>& versionString,
+ const vector<String16>& packageName, const vector<String16>& installer) {
vector<wp<PackageInfoListener>> broadcastList;
{
lock_guard<mutex> lock(mMutex); // Exclusively lock for updates.
@@ -121,7 +130,9 @@ void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
mMap.clear();
for (size_t j = 0; j < uid.size(); j++) {
string package = string(String8(packageName[j]).string());
- mMap[std::make_pair(uid[j], package)] = AppData(versionCode[j]);
+ mMap[std::make_pair(uid[j], package)] =
+ AppData(versionCode[j], string(String8(versionString[j]).string()),
+ string(String8(installer[j]).string()));
}
for (const auto& kv : deletedApps) {
@@ -150,23 +161,30 @@ void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
}
void UidMap::updateApp(const int64_t& timestamp, const String16& app_16, const int32_t& uid,
- const int64_t& versionCode) {
+ const int64_t& versionCode, const String16& versionString,
+ const String16& installer) {
vector<wp<PackageInfoListener>> broadcastList;
string appName = string(String8(app_16).string());
{
lock_guard<mutex> lock(mMutex);
int32_t prevVersion = 0;
+ string prevVersionString = "";
+ string newVersionString = string(String8(versionString).string());
bool found = false;
auto it = mMap.find(std::make_pair(uid, appName));
if (it != mMap.end()) {
found = true;
prevVersion = it->second.versionCode;
+ prevVersionString = it->second.versionString;
it->second.versionCode = versionCode;
+ it->second.versionString = newVersionString;
+ it->second.installer = string(String8(installer).string());
it->second.deleted = false;
}
if (!found) {
// Otherwise, we need to add an app at this uid.
- mMap[std::make_pair(uid, appName)] = AppData(versionCode);
+ mMap[std::make_pair(uid, appName)] =
+ AppData(versionCode, newVersionString, string(String8(installer).string()));
} else {
// Only notify the listeners if this is an app upgrade. If this app is being installed
// for the first time, then we don't notify the listeners.
@@ -174,7 +192,8 @@ void UidMap::updateApp(const int64_t& timestamp, const String16& app_16, const i
// app after deletion.
getListenerListCopyLocked(&broadcastList);
}
- mChanges.emplace_back(false, timestamp, appName, uid, versionCode, prevVersion);
+ mChanges.emplace_back(false, timestamp, appName, uid, versionCode, newVersionString,
+ prevVersion, prevVersionString);
mBytesUsed += kBytesChangeRecord;
ensureBytesUsedBelowLimit();
StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
@@ -226,10 +245,12 @@ void UidMap::removeApp(const int64_t& timestamp, const String16& app_16, const i
lock_guard<mutex> lock(mMutex);
int64_t prevVersion = 0;
+ string prevVersionString = "";
auto key = std::make_pair(uid, app);
auto it = mMap.find(key);
if (it != mMap.end() && !it->second.deleted) {
prevVersion = it->second.versionCode;
+ prevVersionString = it->second.versionString;
it->second.deleted = true;
mDeletedApps.push_back(key);
}
@@ -240,7 +261,7 @@ void UidMap::removeApp(const int64_t& timestamp, const String16& app_16, const i
mMap.erase(oldest);
StatsdStats::getInstance().noteUidMapAppDeletionDropped();
}
- mChanges.emplace_back(true, timestamp, app, uid, 0, prevVersion);
+ mChanges.emplace_back(true, timestamp, app, uid, 0, "", prevVersion, prevVersionString);
mBytesUsed += kBytesChangeRecord;
ensureBytesUsedBelowLimit();
StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
@@ -315,8 +336,9 @@ size_t UidMap::getBytesUsed() const {
return mBytesUsed;
}
-void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key,
- std::set<string> *str_set, ProtoOutputStream* proto) {
+void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::set<string>* str_set,
+ bool includeVersionStrings, bool includeInstaller,
+ ProtoOutputStream* proto) {
lock_guard<mutex> lock(mMutex); // Lock for updates
for (const ChangeRecord& record : mChanges) {
@@ -330,8 +352,22 @@ void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key,
str_set->insert(record.package);
proto->write(FIELD_TYPE_UINT64 | FIELD_ID_CHANGE_PACKAGE_HASH,
(long long)Hash64(record.package));
+ if (includeVersionStrings) {
+ str_set->insert(record.versionString);
+ proto->write(FIELD_TYPE_UINT64 | FIELD_ID_CHANGE_NEW_VERSION_STRING_HASH,
+ (long long)Hash64(record.versionString));
+ str_set->insert(record.prevVersionString);
+ proto->write(FIELD_TYPE_UINT64 | FIELD_ID_CHANGE_PREV_VERSION_STRING_HASH,
+ (long long)Hash64(record.prevVersionString));
+ }
} else {
proto->write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_PACKAGE, record.package);
+ if (includeVersionStrings) {
+ proto->write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_NEW_VERSION_STRING,
+ record.versionString);
+ proto->write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_PREV_VERSION_STRING,
+ record.prevVersionString);
+ }
}
proto->write(FIELD_TYPE_INT32 | FIELD_ID_CHANGE_UID, (int)record.uid);
@@ -354,8 +390,26 @@ void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key,
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,
@@ -391,8 +445,9 @@ void UidMap::printUidMap(int out) const {
for (const auto& kv : mMap) {
if (!kv.second.deleted) {
- dprintf(out, "%s, v%" PRId64 " (%i)\n", kv.first.second.c_str(), kv.second.versionCode,
- kv.first.first);
+ dprintf(out, "%s, v%" PRId64 ", %s, %s (%i)\n", kv.first.second.c_str(),
+ kv.second.versionCode, kv.second.versionString.c_str(),
+ kv.second.installer.c_str(), kv.first.first);
}
}
}
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index 4598369f1222..75ff507ef09a 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -44,12 +44,16 @@ namespace statsd {
struct AppData {
int64_t versionCode;
+ string versionString;
+ string installer;
bool deleted;
// Empty constructor needed for unordered map.
AppData() {
}
- AppData(const int64_t v) : versionCode(v), deleted(false){};
+
+ AppData(const int64_t v, const string& versionString, const string& installer)
+ : versionCode(v), versionString(versionString), installer(installer), deleted(false){};
};
// When calling appendUidMap, we retrieve all the ChangeRecords since the last
@@ -61,15 +65,20 @@ struct ChangeRecord {
const int32_t uid;
const int64_t version;
const int64_t prevVersion;
+ const string versionString;
+ const string prevVersionString;
ChangeRecord(const bool isDeletion, const int64_t timestampNs, const string& package,
- const int32_t uid, const int64_t version, const int64_t prevVersion)
+ const int32_t uid, const int64_t version, const string versionString,
+ const int64_t prevVersion, const string prevVersionString)
: deletion(isDeletion),
timestampNs(timestampNs),
package(package),
uid(uid),
version(version),
- prevVersion(prevVersion) {
+ prevVersion(prevVersion),
+ versionString(versionString),
+ prevVersionString(prevVersionString) {
}
};
@@ -87,10 +96,12 @@ public:
* tuple, ie. uid[j] corresponds to packageName[j] with versionCode[j].
*/
void updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
- const vector<int64_t>& versionCode, const vector<String16>& packageName);
+ const vector<int64_t>& versionCode, const vector<String16>& versionString,
+ const vector<String16>& packageName, const vector<String16>& installer);
void updateApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid,
- const int64_t& versionCode);
+ const int64_t& versionCode, const String16& versionString,
+ const String16& installer);
void removeApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid);
// Returns true if the given uid contains the specified app (eg. com.google.android.gms).
@@ -127,8 +138,9 @@ public:
// Gets all snapshots and changes that have occurred since the last output.
// If every config key has received a change or snapshot record, then this
// record is deleted.
- void appendUidMap(const int64_t& timestamp, const ConfigKey& key,
- std::set<string> *str_set, util::ProtoOutputStream* proto);
+ void appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::set<string>* str_set,
+ bool includeVersionStrings, bool includeInstaller,
+ util::ProtoOutputStream* proto);
// Forces the output to be cleared. We still generate a snapshot based on the current state.
// This results in extra data uploaded but helps us reconstruct the uid mapping on the server
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 5d0f3d1db8c9..32ee5af9ee21 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -233,6 +233,14 @@ message UidMapping {
optional bool deleted = 4;
optional uint64 name_hash = 5;
+
+ optional string version_string = 6;
+
+ optional uint64 version_string_hash = 7;
+
+ optional string installer = 8;
+
+ optional uint64 installer_hash = 9;
}
optional int64 elapsed_timestamp_nanos = 1;
@@ -250,6 +258,10 @@ message UidMapping {
optional int64 new_version = 5;
optional int64 prev_version = 6;
optional uint64 app_hash = 7;
+ optional string new_version_string = 8;
+ optional string prev_version_string = 9;
+ optional uint64 new_version_string_hash = 10;
+ optional uint64 prev_version_string_hash = 11;
}
repeated Change changes = 2;
}
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index aa789c799056..f955df29aee0 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -409,6 +409,10 @@ message StatsdConfig {
repeated MetricActivation metric_activation = 17;
+ optional bool version_strings_in_metric_report = 18;
+
+ optional bool installer_in_metric_report = 19;
+
// Field number 1000 is reserved for later use.
reserved 1000;
}
diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp
index 4c6671dcd663..2b9528f7d1de 100644
--- a/cmds/statsd/tests/LogEntryMatcher_test.cpp
+++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp
@@ -148,8 +148,12 @@ TEST(AtomMatcherTest, TestAttributionMatcher) {
uidMap.updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
+ {android::String16("v1"), android::String16("v1"), android::String16("v2"),
+ android::String16("v1"), android::String16("v2")},
{android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
- android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);
+ android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+ {android::String16(""), android::String16(""), android::String16(""),
+ android::String16(""), android::String16("")});
EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
@@ -297,8 +301,12 @@ TEST(AtomMatcherTest, TestNeqAnyStringMatcher) {
UidMap uidMap;
uidMap.updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
+ {android::String16("v1"), android::String16("v1"), android::String16("v2"),
+ android::String16("v1"), android::String16("v2")},
{android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
- android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);
+ android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+ {android::String16(""), android::String16(""), android::String16(""),
+ android::String16(""), android::String16("")});
AttributionNodeInternal attribution_node1;
attribution_node1.set_uid(1111);
@@ -372,8 +380,12 @@ TEST(AtomMatcherTest, TestEqAnyStringMatcher) {
UidMap uidMap;
uidMap.updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
+ {android::String16("v1"), android::String16("v1"), android::String16("v2"),
+ android::String16("v1"), android::String16("v2")},
{android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
- android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);
+ android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+ {android::String16(""), android::String16(""), android::String16(""),
+ android::String16(""), android::String16("")});
AttributionNodeInternal attribution_node1;
attribution_node1.set_uid(1067);
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 8864252bcf4b..355df2986a0b 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -153,7 +153,8 @@ TEST(StatsLogProcessorTest, TestUidMapHasSnapshot) {
// Setup simple config key corresponding to empty config.
sp<UidMap> m = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- m->updateMap(1, {1, 2}, {1, 2}, {String16("p1"), String16("p2")});
+ m->updateMap(1, {1, 2}, {1, 2}, {String16("v1"), String16("v2")},
+ {String16("p1"), String16("p2")}, {String16(""), String16("")});
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> subscriberAlarmMonitor;
int broadcastCount = 0;
@@ -182,7 +183,8 @@ TEST(StatsLogProcessorTest, TestEmptyConfigHasNoUidMap) {
// Setup simple config key corresponding to empty config.
sp<UidMap> m = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- m->updateMap(1, {1, 2}, {1, 2}, {String16("p1"), String16("p2")});
+ m->updateMap(1, {1, 2}, {1, 2}, {String16("v1"), String16("v2")},
+ {String16("p1"), String16("p2")}, {String16(""), String16("")});
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> subscriberAlarmMonitor;
int broadcastCount = 0;
diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp
index 99082cc647f6..f0d9cf188661 100644
--- a/cmds/statsd/tests/UidMap_test.cpp
+++ b/cmds/statsd/tests/UidMap_test.cpp
@@ -71,14 +71,20 @@ TEST(UidMapTest, TestMatching) {
vector<int32_t> uids;
vector<int64_t> versions;
vector<String16> apps;
+ vector<String16> versionStrings;
+ vector<String16> installers;
uids.push_back(1000);
uids.push_back(1000);
+ versionStrings.push_back(String16("v1"));
+ versionStrings.push_back(String16("v1"));
+ installers.push_back(String16(""));
+ installers.push_back(String16(""));
apps.push_back(String16(kApp1.c_str()));
apps.push_back(String16(kApp2.c_str()));
versions.push_back(4);
versions.push_back(5);
- m.updateMap(1, uids, versions, apps);
+ m.updateMap(1, uids, versions, versionStrings, apps, installers);
EXPECT_TRUE(m.hasApp(1000, kApp1));
EXPECT_TRUE(m.hasApp(1000, kApp2));
EXPECT_FALSE(m.hasApp(1000, "not.app"));
@@ -97,14 +103,20 @@ TEST(UidMapTest, TestAddAndRemove) {
vector<int32_t> uids;
vector<int64_t> versions;
vector<String16> apps;
+ vector<String16> versionStrings;
+ vector<String16> installers;
uids.push_back(1000);
uids.push_back(1000);
+ versionStrings.push_back(String16("v1"));
+ versionStrings.push_back(String16("v1"));
+ installers.push_back(String16(""));
+ installers.push_back(String16(""));
apps.push_back(String16(kApp1.c_str()));
apps.push_back(String16(kApp2.c_str()));
versions.push_back(4);
versions.push_back(5);
- m.updateMap(1, uids, versions, apps);
+ m.updateMap(1, uids, versions, versionStrings, apps, installers);
std::set<string> name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
EXPECT_EQ(name_set.size(), 2u);
@@ -112,7 +124,7 @@ TEST(UidMapTest, TestAddAndRemove) {
EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
// Update the app1 version.
- m.updateApp(2, String16(kApp1.c_str()), 1000, 40);
+ m.updateApp(2, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""));
EXPECT_EQ(40, m.getAppVersion(1000, kApp1));
name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
@@ -138,14 +150,15 @@ TEST(UidMapTest, TestAddAndRemove) {
TEST(UidMapTest, TestUpdateApp) {
UidMap m;
- m.updateMap(1, {1000, 1000}, {4, 5}, {String16(kApp1.c_str()), String16(kApp2.c_str())});
+ m.updateMap(1, {1000, 1000}, {4, 5}, {String16("v4"), String16("v5")},
+ {String16(kApp1.c_str()), String16(kApp2.c_str())}, {String16(""), String16("")});
std::set<string> name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
EXPECT_EQ(name_set.size(), 2u);
EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
// Adds a new name for uid 1000.
- m.updateApp(2, String16("NeW_aPP1_NAmE"), 1000, 40);
+ m.updateApp(2, String16("NeW_aPP1_NAmE"), 1000, 40, String16("v40"), String16(""));
name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
EXPECT_EQ(name_set.size(), 3u);
EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
@@ -154,7 +167,7 @@ TEST(UidMapTest, TestUpdateApp) {
EXPECT_TRUE(name_set.find("new_app1_name") != name_set.end());
// This name is also reused by another uid 2000.
- m.updateApp(3, String16("NeW_aPP1_NAmE"), 2000, 1);
+ m.updateApp(3, String16("NeW_aPP1_NAmE"), 2000, 1, String16("v1"), String16(""));
name_set = m.getAppNamesFromUid(2000, true /* returnNormalized */);
EXPECT_EQ(name_set.size(), 1u);
EXPECT_TRUE(name_set.find("NeW_aPP1_NAmE") == name_set.end());
@@ -185,21 +198,26 @@ TEST(UidMapTest, TestOutputIncludesAtLeastOneSnapshot) {
vector<int32_t> uids;
vector<int64_t> versions;
vector<String16> apps;
+ vector<String16> versionStrings;
+ vector<String16> installers;
uids.push_back(1000);
apps.push_back(String16(kApp2.c_str()));
+ versionStrings.push_back(String16("v1"));
+ installers.push_back(String16(""));
versions.push_back(5);
- m.updateMap(1, uids, versions, apps);
+ m.updateMap(1, uids, versions, versionStrings, apps, installers);
// Set the last timestamp for this config key to be newer.
m.mLastUpdatePerConfigKey[config1] = 2;
ProtoOutputStream proto;
- m.appendUidMap(3, config1, nullptr, &proto);
+ m.appendUidMap(3, config1, nullptr, true, true, &proto);
// Check there's still a uidmap attached this one.
UidMapping results;
protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
+ EXPECT_EQ("v1", results.snapshots(0).package_info(0).version_string());
}
TEST(UidMapTest, TestRemovedAppRetained) {
@@ -209,15 +227,19 @@ TEST(UidMapTest, TestRemovedAppRetained) {
m.OnConfigUpdated(config1);
vector<int32_t> uids;
vector<int64_t> versions;
+ vector<String16> versionStrings;
+ vector<String16> installers;
vector<String16> apps;
uids.push_back(1000);
apps.push_back(String16(kApp2.c_str()));
versions.push_back(5);
- m.updateMap(1, uids, versions, apps);
+ versionStrings.push_back(String16("v5"));
+ installers.push_back(String16(""));
+ m.updateMap(1, uids, versions, versionStrings, apps, installers);
m.removeApp(2, String16(kApp2.c_str()), 1000);
ProtoOutputStream proto;
- m.appendUidMap(3, config1, nullptr, &proto);
+ m.appendUidMap(3, config1, nullptr, true, true, &proto);
// Snapshot should still contain this item as deleted.
UidMapping results;
@@ -233,30 +255,34 @@ TEST(UidMapTest, TestRemovedAppOverGuardrail) {
m.OnConfigUpdated(config1);
vector<int32_t> uids;
vector<int64_t> versions;
+ vector<String16> versionStrings;
+ vector<String16> installers;
vector<String16> apps;
const int maxDeletedApps = StatsdStats::kMaxDeletedAppsInUidMap;
for (int j = 0; j < maxDeletedApps + 10; j++) {
uids.push_back(j);
apps.push_back(String16(kApp1.c_str()));
versions.push_back(j);
+ versionStrings.push_back(String16("v"));
+ installers.push_back(String16(""));
}
- m.updateMap(1, uids, versions, apps);
+ m.updateMap(1, uids, versions, versionStrings, apps, installers);
// First, verify that we have the expected number of items.
UidMapping results;
ProtoOutputStream proto;
- m.appendUidMap(3, config1, nullptr, &proto);
+ m.appendUidMap(3, config1, nullptr, true, true, &proto);
protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(maxDeletedApps + 10, results.snapshots(0).package_info_size());
// Now remove all the apps.
- m.updateMap(1, uids, versions, apps);
+ m.updateMap(1, uids, versions, versionStrings, apps, installers);
for (int j = 0; j < maxDeletedApps + 10; j++) {
m.removeApp(4, String16(kApp1.c_str()), j);
}
proto.clear();
- m.appendUidMap(5, config1, nullptr, &proto);
+ m.appendUidMap(5, config1, nullptr, true, true, &proto);
// Snapshot drops the first nine items.
protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(maxDeletedApps, results.snapshots(0).package_info_size());
@@ -272,6 +298,8 @@ TEST(UidMapTest, TestClearingOutput) {
vector<int32_t> uids;
vector<int64_t> versions;
+ vector<String16> versionStrings;
+ vector<String16> installers;
vector<String16> apps;
uids.push_back(1000);
uids.push_back(1000);
@@ -279,45 +307,49 @@ TEST(UidMapTest, TestClearingOutput) {
apps.push_back(String16(kApp2.c_str()));
versions.push_back(4);
versions.push_back(5);
- m.updateMap(1, uids, versions, apps);
+ versionStrings.push_back(String16("v4"));
+ versionStrings.push_back(String16("v5"));
+ installers.push_back(String16(""));
+ installers.push_back(String16(""));
+ m.updateMap(1, uids, versions, versionStrings, apps, installers);
ProtoOutputStream proto;
- m.appendUidMap(2, config1, nullptr, &proto);
+ m.appendUidMap(2, config1, nullptr, true, true, &proto);
UidMapping results;
protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
// We have to keep at least one snapshot in memory at all times.
proto.clear();
- m.appendUidMap(2, config1, nullptr, &proto);
+ m.appendUidMap(2, config1, nullptr, true, true, &proto);
protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
// Now add another configuration.
m.OnConfigUpdated(config2);
- m.updateApp(5, String16(kApp1.c_str()), 1000, 40);
+ m.updateApp(5, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""));
EXPECT_EQ(1U, m.mChanges.size());
proto.clear();
- m.appendUidMap(6, config1, nullptr, &proto);
+ m.appendUidMap(6, config1, nullptr, true, true, &proto);
protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
EXPECT_EQ(1, results.changes_size());
EXPECT_EQ(1U, m.mChanges.size());
// Add another delta update.
- m.updateApp(7, String16(kApp2.c_str()), 1001, 41);
+ m.updateApp(7, String16(kApp2.c_str()), 1001, 41, String16("v41"), String16(""));
EXPECT_EQ(2U, m.mChanges.size());
// We still can't remove anything.
proto.clear();
- m.appendUidMap(8, config1, nullptr, &proto);
+ m.appendUidMap(8, config1, nullptr, true, true, &proto);
protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
EXPECT_EQ(1, results.changes_size());
EXPECT_EQ(2U, m.mChanges.size());
proto.clear();
- m.appendUidMap(9, config2, nullptr, &proto);
+ m.appendUidMap(9, config2, nullptr, true, true, &proto);
protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
EXPECT_EQ(2, results.changes_size());
@@ -335,19 +367,23 @@ TEST(UidMapTest, TestMemoryComputed) {
vector<int32_t> uids;
vector<int64_t> versions;
vector<String16> apps;
+ vector<String16> versionStrings;
+ vector<String16> installers;
uids.push_back(1000);
apps.push_back(String16(kApp1.c_str()));
versions.push_back(1);
- m.updateMap(1, uids, versions, apps);
+ versionStrings.push_back(String16("v1"));
+ installers.push_back(String16(""));
+ m.updateMap(1, uids, versions, versionStrings, apps, installers);
- m.updateApp(3, String16(kApp1.c_str()), 1000, 40);
+ m.updateApp(3, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""));
ProtoOutputStream proto;
vector<uint8_t> bytes;
- m.appendUidMap(2, config1, nullptr, &proto);
+ m.appendUidMap(2, config1, nullptr, true, true, &proto);
size_t prevBytes = m.mBytesUsed;
- m.appendUidMap(4, config1, nullptr, &proto);
+ m.appendUidMap(4, config1, nullptr, true, true, &proto);
EXPECT_TRUE(m.mBytesUsed < prevBytes);
}
@@ -361,21 +397,27 @@ TEST(UidMapTest, TestMemoryGuardrail) {
size_t startBytes = m.mBytesUsed;
vector<int32_t> uids;
vector<int64_t> versions;
+ vector<String16> versionStrings;
+ vector<String16> installers;
vector<String16> apps;
for (int i = 0; i < 100; i++) {
uids.push_back(1);
buf = "EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY." + to_string(i);
apps.push_back(String16(buf.c_str()));
versions.push_back(1);
+ versionStrings.push_back(String16("v1"));
+ installers.push_back(String16(""));
}
- m.updateMap(1, uids, versions, apps);
+ m.updateMap(1, uids, versions, versionStrings, apps, installers);
- m.updateApp(3, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 2);
+ m.updateApp(3, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 2,
+ String16("v2"), String16(""));
EXPECT_EQ(1U, m.mChanges.size());
// Now force deletion by limiting the memory to hold one delta change.
- m.maxBytesOverride = 80; // Since the app string alone requires >45 characters.
- m.updateApp(5, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 4);
+ m.maxBytesOverride = 120; // Since the app string alone requires >45 characters.
+ m.updateApp(5, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 4,
+ String16("v4"), String16(""));
EXPECT_EQ(1U, m.mChanges.size());
}
diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
index 5c47af797eea..a9841c91ada2 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -69,8 +69,10 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid) {
// Here it assumes that GMS core has two uids.
processor->getUidMap()->updateMap(
1, {222, 444, 111, 333}, {1, 1, 2, 2},
+ {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
{String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
- String16("APP3")});
+ String16("APP3")},
+ {String16(""), String16(""), String16(""), String16("")});
// GMS core node is in the middle.
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
@@ -215,8 +217,10 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain) {
// Here it assumes that GMS core has two uids.
processor->getUidMap()->updateMap(
1, {222, 444, 111, 333}, {1, 1, 2, 2},
+ {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
{String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
- String16("APP3")});
+ String16("APP3")},
+ {String16(""), String16(""), String16(""), String16("")});
// GMS core node is in the middle.
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
diff --git a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
index 3cb553fd9a16..2b0285b37473 100644
--- a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
@@ -132,7 +132,8 @@ TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
// This is a new installation, so there shouldn't be a split (should be same as the without
// split case).
- service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2);
+ service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
+ String16(""));
// Goes into the second bucket.
service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
@@ -145,11 +146,13 @@ TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
SendConfig(service, MakeConfig());
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
- service.mUidMap->updateMap(start, {1}, {1}, {String16(kApp1.c_str())});
+ service.mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
+ {String16("")});
// Force the uidmap to update at timestamp 2.
service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
- service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2);
+ service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
+ String16(""));
// Goes into the second bucket.
service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
@@ -168,7 +171,8 @@ TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
SendConfig(service, MakeConfig());
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
- service.mUidMap->updateMap(start, {1}, {1}, {String16(kApp1.c_str())});
+ service.mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
+ {String16("")});
// Force the uidmap to update at timestamp 2.
service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
@@ -189,13 +193,14 @@ TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
StatsService service(nullptr);
// Partial buckets don't occur when app is first installed.
- service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1);
+ service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
SendConfig(service, MakeValueMetricConfig(0));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
- service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2);
+ service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2,
+ String16("v2"), String16(""));
ConfigMetricsReport report =
GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100, true);
@@ -206,14 +211,15 @@ TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
TEST(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
StatsService service(nullptr);
// Partial buckets don't occur when app is first installed.
- service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1);
+ service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
SendConfig(service, MakeValueMetricConfig(60 * NS_PER_SEC /* One minute */));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2;
service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
- service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2);
+ service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"),
+ String16(""));
ConfigMetricsReport report =
GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC, true);
@@ -229,13 +235,14 @@ TEST(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) {
StatsService service(nullptr);
// Partial buckets don't occur when app is first installed.
- service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1);
+ service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
SendConfig(service, MakeGaugeMetricConfig(0));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
- service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2);
+ service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2,
+ String16("v2"), String16(""));
ConfigMetricsReport report =
GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100, true);
@@ -246,14 +253,15 @@ TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) {
TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) {
StatsService service(nullptr);
// Partial buckets don't occur when app is first installed.
- service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1);
+ service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
SendConfig(service, MakeGaugeMetricConfig(60 * NS_PER_SEC /* One minute */));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2;
service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
- service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2);
+ service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"),
+ String16(""));
ConfigMetricsReport report =
GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC, true);
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 851e35b5e9f0..39b327c3674b 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -1320,18 +1320,6 @@ Landroid/R$styleable;->Window_windowFrame:I
Landroid/security/Credentials;->convertToPem([Ljava/security/cert/Certificate;)[B
Landroid/security/IKeyChainService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeyChainService;
Landroid/security/IKeyChainService;->requestPrivateKey(Ljava/lang/String;)Ljava/lang/String;
-Landroid/security/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/IKeystoreService;
-Landroid/security/IKeystoreService;->clear_uid(J)I
-Landroid/security/IKeystoreService;->del(Ljava/lang/String;I)I
-Landroid/security/IKeystoreService;->exist(Ljava/lang/String;I)I
-Landroid/security/IKeystoreService;->generateKey(Ljava/lang/String;Landroid/security/keymaster/KeymasterArguments;[BIILandroid/security/keymaster/KeyCharacteristics;)I
-Landroid/security/IKeystoreService;->get(Ljava/lang/String;I)[B
-Landroid/security/IKeystoreService;->getState(I)I
-Landroid/security/IKeystoreService;->insert(Ljava/lang/String;[BII)I
-Landroid/security/IKeystoreService;->is_hardware_backed(Ljava/lang/String;)I
-Landroid/security/IKeystoreService;->list(Ljava/lang/String;I)[Ljava/lang/String;
-Landroid/security/IKeystoreService;->reset()I
-Landroid/security/IKeystoreService;->ungrant(Ljava/lang/String;I)I
Landroid/security/keymaster/KeymasterBlobArgument;-><init>(ILandroid/os/Parcel;)V
Landroid/security/keymaster/KeymasterBlobArgument;-><init>(I[B)V
Landroid/security/keymaster/KeymasterBlobArgument;->blob:[B
@@ -1343,6 +1331,17 @@ Landroid/security/keymaster/KeymasterIntArgument;->value:I
Landroid/security/keymaster/KeymasterLongArgument;-><init>(IJ)V
Landroid/security/keymaster/KeymasterLongArgument;-><init>(ILandroid/os/Parcel;)V
Landroid/security/keymaster/KeymasterLongArgument;->value:J
+Landroid/security/keystore/IKeystoreService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/security/keystore/IKeystoreService;
+Landroid/security/keystore/IKeystoreService;->clear_uid(J)I
+Landroid/security/keystore/IKeystoreService;->del(Ljava/lang/String;I)I
+Landroid/security/keystore/IKeystoreService;->exist(Ljava/lang/String;I)I
+Landroid/security/keystore/IKeystoreService;->get(Ljava/lang/String;I)[B
+Landroid/security/keystore/IKeystoreService;->getState(I)I
+Landroid/security/keystore/IKeystoreService;->insert(Ljava/lang/String;[BII)I
+Landroid/security/keystore/IKeystoreService;->is_hardware_backed(Ljava/lang/String;)I
+Landroid/security/keystore/IKeystoreService;->list(Ljava/lang/String;I)[Ljava/lang/String;
+Landroid/security/keystore/IKeystoreService;->reset()I
+Landroid/security/keystore/IKeystoreService;->ungrant(Ljava/lang/String;I)I
Landroid/service/carrier/ICarrierMessagingCallback$Stub;-><init>()V
Landroid/service/carrier/ICarrierMessagingService;->filterSms(Landroid/service/carrier/MessagePdu;Ljava/lang/String;IILandroid/service/carrier/ICarrierMessagingCallback;)V
Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 2be5dc966746..9e109c534ba9 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1625,9 +1625,6 @@ public class AppOpsManager {
case AppOpsManager.OP_READ_CALL_LOG:
case AppOpsManager.OP_WRITE_CALL_LOG:
case AppOpsManager.OP_PROCESS_OUTGOING_CALLS: {
- if (sSmsAndCallLogRestrictionEnabled.get() < 0) {
- startWatchingSmsRestrictionEnabled();
- }
if (sSmsAndCallLogRestrictionEnabled.get() == 1) {
return AppOpsManager.MODE_DEFAULT;
}
@@ -1640,26 +1637,24 @@ public class AppOpsManager {
private static final AtomicInteger sSmsAndCallLogRestrictionEnabled = new AtomicInteger(-1);
// STOPSHIP b/118520006: Hardcode the default values once the feature is stable.
- private static void startWatchingSmsRestrictionEnabled() {
+ static {
final Context context = ActivityThread.currentApplication();
- if (context == null) {
- // Should never happen
- return;
+ if (context != null) {
+ sSmsAndCallLogRestrictionEnabled.set(ActivityThread.currentActivityThread()
+ .getIntCoreSetting(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0));
+
+ final Uri uri =
+ Settings.Global.getUriFor(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED);
+ context.getContentResolver().registerContentObserver(uri, false, new ContentObserver(
+ context.getMainThreadHandler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ sSmsAndCallLogRestrictionEnabled.set(Settings.Global.getInt(
+ context.getContentResolver(),
+ Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0));
+ }
+ });
}
-
- sSmsAndCallLogRestrictionEnabled.set(ActivityThread.currentActivityThread()
- .getIntCoreSetting(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0));
-
- final Uri uri = Settings.Global.getUriFor(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED);
- context.getContentResolver().registerContentObserver(uri, false, new ContentObserver(
- context.getMainThreadHandler()) {
- @Override
- public void onChange(boolean selfChange) {
- sSmsAndCallLogRestrictionEnabled.set(Settings.Global.getInt(
- context.getContentResolver(),
- Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0));
- }
- });
}
/**
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index fcd9a0511265..8bb704d76e85 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2277,6 +2277,15 @@ public class ApplicationPackageManager extends PackageManager {
}
@Override
+ public boolean canSuspendPackage(String packageName) {
+ try {
+ return mPM.canSuspendPackageForUser(packageName, mContext.getUserId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
public Bundle getSuspendedPackageAppExtras() {
final PersistableBundle extras;
try {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index dc707e892d9a..9837deb6143c 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -140,6 +140,13 @@ class ReceiverRestrictedContext extends ContextWrapper {
throw new ReceiverCallNotAllowedException(
"BroadcastReceiver components are not allowed to bind to services");
}
+
+ @Override
+ public boolean bindIsolatedService(Intent service, ServiceConnection conn, int flags,
+ String instanceName) {
+ throw new ReceiverCallNotAllowedException(
+ "BroadcastReceiver components are not allowed to bind to services");
+ }
}
/**
@@ -1630,14 +1637,25 @@ class ContextImpl extends Context {
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
- return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
+ return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), getUser());
+ }
+
+ @Override
+ public boolean bindIsolatedService(Intent service, ServiceConnection conn,
+ int flags, String instanceName) {
+ warnIfCallingFromSystemProcess();
+ if (instanceName == null) {
+ throw new NullPointerException("null instanceName");
+ }
+ return bindServiceCommon(service, conn, flags, instanceName, mMainThread.getHandler(),
+ getUser());
}
/** @hide */
@Override
public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
- return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), user);
+ return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), user);
}
/** @hide */
@@ -1647,7 +1665,7 @@ class ContextImpl extends Context {
if (handler == null) {
throw new IllegalArgumentException("handler must not be null.");
}
- return bindServiceCommon(service, conn, flags, handler, user);
+ return bindServiceCommon(service, conn, flags, null, handler, user);
}
/** @hide */
@@ -1669,7 +1687,8 @@ class ContextImpl extends Context {
return mMainThread.getHandler();
}
- private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
+ private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
+ String instanceName, Handler
handler, UserHandle user) {
// Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
IServiceConnection sd;
@@ -1690,10 +1709,10 @@ class ContextImpl extends Context {
flags |= BIND_WAIVE_PRIORITY;
}
service.prepareToLeaveProcess(this);
- int res = ActivityManager.getService().bindService(
+ int res = ActivityManager.getService().bindIsolatedService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
- sd, flags, getOpPackageName(), user.getIdentifier());
+ sd, flags, instanceName, getOpPackageName(), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index e2312a539ae4..f27c6677ed22 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -133,9 +133,13 @@ interface IActivityManager {
in String resolvedType, boolean requireForeground, in String callingPackage, int userId);
int stopService(in IApplicationThread caller, in Intent service,
in String resolvedType, int userId);
+ // Currently keeping old bindService because it is on the greylist
int bindService(in IApplicationThread caller, in IBinder token, in Intent service,
in String resolvedType, in IServiceConnection connection, int flags,
in String callingPackage, int userId);
+ int bindIsolatedService(in IApplicationThread caller, in IBinder token, in Intent service,
+ in String resolvedType, in IServiceConnection connection, int flags,
+ in String instanceName, in String callingPackage, int userId);
boolean unbindService(in IServiceConnection connection);
void publishService(in IBinder token, in Intent intent, in IBinder service);
void setDebugApp(in String packageName, boolean waitForDebugger, boolean persistent);
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index bd9cf6dda7ff..362f4aedc900 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -88,6 +88,8 @@ interface INotificationManager
ParceledListSlice getRecentNotifyingAppsForUser(int userId);
int getBlockedAppCount(int userId);
boolean areChannelsBypassingDnd();
+ int getAppsBypassingDndCount(int uid);
+ ParceledListSlice getNotificationChannelsBypassingDnd(String pkg, int userId);
// TODO: Remove this when callers have been migrated to the equivalent
// INotificationListener method.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index df37a02047b5..450efdf16656 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -207,7 +207,8 @@ public class Notification implements Parcelable
private static final int MAX_REPLY_HISTORY = 5;
/**
- * Maximum numbers of action buttons in a notification.
+ * Maximum number of (generic) action buttons in a notification (contextual action buttons are
+ * handled separately).
* @hide
*/
public static final int MAX_ACTION_BUTTONS = 3;
@@ -1421,6 +1422,12 @@ public class Notification implements Parcelable
*/
public static final int SEMANTIC_ACTION_CALL = 10;
+ /**
+ * {@code SemanticAction}: Contextual action - dependent on the current notification. E.g.
+ * open a Map application with an address shown in the notification.
+ */
+ public static final int SEMANTIC_ACTION_CONTEXTUAL_SUGGESTION = 11;
+
private final Bundle mExtras;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private Icon mIcon;
@@ -2042,7 +2049,8 @@ public class Notification implements Parcelable
SEMANTIC_ACTION_UNMUTE,
SEMANTIC_ACTION_THUMBS_UP,
SEMANTIC_ACTION_THUMBS_DOWN,
- SEMANTIC_ACTION_CALL
+ SEMANTIC_ACTION_CALL,
+ SEMANTIC_ACTION_CONTEXTUAL_SUGGESTION
})
@Retention(RetentionPolicy.SOURCE)
public @interface SemanticAction {}
@@ -4962,6 +4970,18 @@ public class Notification implements Parcelable
result);
}
+ private static List<Notification.Action> filterOutContextualActions(
+ List<Notification.Action> actions) {
+ List<Notification.Action> nonContextualActions = new ArrayList<>();
+ for (Notification.Action action : actions) {
+ if (action.getSemanticAction()
+ != Action.SEMANTIC_ACTION_CONTEXTUAL_SUGGESTION) {
+ nonContextualActions.add(action);
+ }
+ }
+ return nonContextualActions;
+ }
+
private RemoteViews applyStandardTemplateWithActions(int layoutId,
StandardTemplateParams p, TemplateBindResult result) {
RemoteViews big = applyStandardTemplate(layoutId, p, result);
@@ -4970,7 +4990,11 @@ public class Notification implements Parcelable
boolean validRemoteInput = false;
- int N = mActions.size();
+ // In the UI contextual actions appear separately from the standard actions, so we
+ // filter them out here.
+ List<Notification.Action> nonContextualActions = filterOutContextualActions(mActions);
+
+ int N = nonContextualActions.size();
boolean emphazisedMode = mN.fullScreenIntent != null && !p.ambient;
big.setBoolean(R.id.actions, "setEmphasizedMode", emphazisedMode);
if (N > 0) {
@@ -4979,7 +5003,8 @@ public class Notification implements Parcelable
big.setViewLayoutMarginBottomDimen(R.id.notification_action_list_margin_target, 0);
if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS;
for (int i=0; i<N; i++) {
- Action action = mActions.get(i);
+ Action action = nonContextualActions.get(i);
+
boolean actionHasValidInput = hasValidRemoteInput(action);
validRemoteInput |= actionHasValidInput;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 9f8ae0bb6ab3..004417b80e26 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2906,8 +2906,9 @@ public abstract class Context {
* @param flags Operation options for the binding. May be 0,
* {@link #BIND_AUTO_CREATE}, {@link #BIND_DEBUG_UNBIND},
* {@link #BIND_NOT_FOREGROUND}, {@link #BIND_ABOVE_CLIENT},
- * {@link #BIND_ALLOW_OOM_MANAGEMENT}, or
- * {@link #BIND_WAIVE_PRIORITY}.
+ * {@link #BIND_ALLOW_OOM_MANAGEMENT}, {@link #BIND_WAIVE_PRIORITY}.
+ * {@link #BIND_IMPORTANT}, or
+ * {@link #BIND_ADJUST_WITH_ACTIVITY}.
* @return {@code true} if the system is in the process of bringing up a
* service that your client has permission to bind to; {@code false}
* if the system couldn't find the service or if your client doesn't
@@ -2923,11 +2924,38 @@ public abstract class Context {
* @see #BIND_AUTO_CREATE
* @see #BIND_DEBUG_UNBIND
* @see #BIND_NOT_FOREGROUND
+ * @see #BIND_ABOVE_CLIENT
+ * @see #BIND_ALLOW_OOM_MANAGEMENT
+ * @see #BIND_WAIVE_PRIORITY
+ * @see #BIND_IMPORTANT
+ * @see #BIND_ADJUST_WITH_ACTIVITY
*/
public abstract boolean bindService(@RequiresPermission Intent service,
@NonNull ServiceConnection conn, @BindServiceFlags int flags);
/**
+ * Variation of {@link #bindService} that, in the specific case of isolated
+ * services, allows the caller to generate multiple instances of a service
+ * from a single component declaration.
+ *
+ * @param service Identifies the service to connect to. The Intent must
+ * specify an explicit component name.
+ * @param conn Receives information as the service is started and stopped.
+ * This must be a valid ServiceConnection object; it must not be null.
+ * @param flags Operation options for the binding as per {@link #bindService}.
+ * @param instanceName Unique identifier for the service instance. Each unique
+ * name here will result in a different service instance being created.
+ * @return Returns success of binding as per {@link #bindService}.
+ *
+ * @throws SecurityException If the caller does not have permission to access the service
+ *
+ * @see #bindService
+ */
+ public abstract boolean bindIsolatedService(@RequiresPermission Intent service,
+ @NonNull ServiceConnection conn, @BindServiceFlags int flags,
+ @NonNull String instanceName);
+
+ /**
* Same as {@link #bindService(Intent, ServiceConnection, int)}, but with an explicit userHandle
* argument for use by system server and other multi-user aware code.
* @hide
@@ -2941,7 +2969,7 @@ public abstract class Context {
}
/**
- * Same as {@link #bindService(Intent, ServiceConnection, int, UserHandle)}, but with an
+ * Same as {@link #bindServiceAsUser(Intent, ServiceConnection, int, UserHandle)}, but with an
* explicit non-null Handler to run the ServiceConnection callbacks on.
*
* @hide
@@ -4307,6 +4335,16 @@ public abstract class Context {
/**
* Use with {@link #getSystemService(String)} to retrieve a
+ * {android.os.IIdmap2} for managing idmap files (used by overlay
+ * packages).
+ *
+ * @see #getSystemService(String)
+ * @hide
+ */
+ public static final String IDMAP_SERVICE = "idmap";
+
+ /**
+ * Use with {@link #getSystemService(String)} to retrieve a
* {@link VrManager} for accessing the VR service.
*
* @see #getSystemService(String)
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index bfad2b42bc94..88696b0e1e4d 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -705,6 +705,12 @@ public class ContextWrapper extends Context {
return mBase.bindService(service, conn, flags);
}
+ @Override
+ public boolean bindIsolatedService(Intent service, ServiceConnection conn,
+ int flags, String instanceName) {
+ return mBase.bindIsolatedService(service, conn, flags, instanceName);
+ }
+
/** @hide */
@Override
public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 02f38a790570..e9b240448eed 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -7508,7 +7508,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putExtra(String, String)
*/
- public String getStringExtra(String name) {
+ public @Nullable String getStringExtra(String name) {
return mExtras == null ? null : mExtras.getString(name);
}
@@ -7522,7 +7522,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putExtra(String, CharSequence)
*/
- public CharSequence getCharSequenceExtra(String name) {
+ public @Nullable CharSequence getCharSequenceExtra(String name) {
return mExtras == null ? null : mExtras.getCharSequence(name);
}
@@ -7536,7 +7536,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putExtra(String, Parcelable)
*/
- public <T extends Parcelable> T getParcelableExtra(String name) {
+ public @Nullable <T extends Parcelable> T getParcelableExtra(String name) {
return mExtras == null ? null : mExtras.<T>getParcelable(name);
}
@@ -7550,7 +7550,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putExtra(String, Parcelable[])
*/
- public Parcelable[] getParcelableArrayExtra(String name) {
+ public @Nullable Parcelable[] getParcelableArrayExtra(String name) {
return mExtras == null ? null : mExtras.getParcelableArray(name);
}
@@ -7565,7 +7565,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putParcelableArrayListExtra(String, ArrayList)
*/
- public <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra(String name) {
+ public @Nullable <T extends Parcelable> ArrayList<T> getParcelableArrayListExtra(String name) {
return mExtras == null ? null : mExtras.<T>getParcelableArrayList(name);
}
@@ -7579,7 +7579,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putExtra(String, Serializable)
*/
- public Serializable getSerializableExtra(String name) {
+ public @Nullable Serializable getSerializableExtra(String name) {
return mExtras == null ? null : mExtras.getSerializable(name);
}
@@ -7594,7 +7594,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putIntegerArrayListExtra(String, ArrayList)
*/
- public ArrayList<Integer> getIntegerArrayListExtra(String name) {
+ public @Nullable ArrayList<Integer> getIntegerArrayListExtra(String name) {
return mExtras == null ? null : mExtras.getIntegerArrayList(name);
}
@@ -7609,7 +7609,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putStringArrayListExtra(String, ArrayList)
*/
- public ArrayList<String> getStringArrayListExtra(String name) {
+ public @Nullable ArrayList<String> getStringArrayListExtra(String name) {
return mExtras == null ? null : mExtras.getStringArrayList(name);
}
@@ -7624,7 +7624,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putCharSequenceArrayListExtra(String, ArrayList)
*/
- public ArrayList<CharSequence> getCharSequenceArrayListExtra(String name) {
+ public @Nullable ArrayList<CharSequence> getCharSequenceArrayListExtra(String name) {
return mExtras == null ? null : mExtras.getCharSequenceArrayList(name);
}
@@ -7638,7 +7638,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putExtra(String, boolean[])
*/
- public boolean[] getBooleanArrayExtra(String name) {
+ public @Nullable boolean[] getBooleanArrayExtra(String name) {
return mExtras == null ? null : mExtras.getBooleanArray(name);
}
@@ -7652,7 +7652,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putExtra(String, byte[])
*/
- public byte[] getByteArrayExtra(String name) {
+ public @Nullable byte[] getByteArrayExtra(String name) {
return mExtras == null ? null : mExtras.getByteArray(name);
}
@@ -7666,7 +7666,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putExtra(String, short[])
*/
- public short[] getShortArrayExtra(String name) {
+ public @Nullable short[] getShortArrayExtra(String name) {
return mExtras == null ? null : mExtras.getShortArray(name);
}
@@ -7680,7 +7680,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putExtra(String, char[])
*/
- public char[] getCharArrayExtra(String name) {
+ public @Nullable char[] getCharArrayExtra(String name) {
return mExtras == null ? null : mExtras.getCharArray(name);
}
@@ -7694,7 +7694,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putExtra(String, int[])
*/
- public int[] getIntArrayExtra(String name) {
+ public @Nullable int[] getIntArrayExtra(String name) {
return mExtras == null ? null : mExtras.getIntArray(name);
}
@@ -7708,7 +7708,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putExtra(String, long[])
*/
- public long[] getLongArrayExtra(String name) {
+ public @Nullable long[] getLongArrayExtra(String name) {
return mExtras == null ? null : mExtras.getLongArray(name);
}
@@ -7722,7 +7722,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putExtra(String, float[])
*/
- public float[] getFloatArrayExtra(String name) {
+ public @Nullable float[] getFloatArrayExtra(String name) {
return mExtras == null ? null : mExtras.getFloatArray(name);
}
@@ -7736,7 +7736,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putExtra(String, double[])
*/
- public double[] getDoubleArrayExtra(String name) {
+ public @Nullable double[] getDoubleArrayExtra(String name) {
return mExtras == null ? null : mExtras.getDoubleArray(name);
}
@@ -7750,7 +7750,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putExtra(String, String[])
*/
- public String[] getStringArrayExtra(String name) {
+ public @Nullable String[] getStringArrayExtra(String name) {
return mExtras == null ? null : mExtras.getStringArray(name);
}
@@ -7764,7 +7764,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putExtra(String, CharSequence[])
*/
- public CharSequence[] getCharSequenceArrayExtra(String name) {
+ public @Nullable CharSequence[] getCharSequenceArrayExtra(String name) {
return mExtras == null ? null : mExtras.getCharSequenceArray(name);
}
@@ -7778,7 +7778,7 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #putExtra(String, Bundle)
*/
- public Bundle getBundleExtra(String name) {
+ public @Nullable Bundle getBundleExtra(String name) {
return mExtras == null ? null : mExtras.getBundle(name);
}
@@ -8584,7 +8584,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getStringExtra(String)
*/
- public @NonNull Intent putExtra(String name, String value) {
+ public @NonNull Intent putExtra(String name, @Nullable String value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8607,7 +8607,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getCharSequenceExtra(String)
*/
- public @NonNull Intent putExtra(String name, CharSequence value) {
+ public @NonNull Intent putExtra(String name, @Nullable CharSequence value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8630,7 +8630,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getParcelableExtra(String)
*/
- public @NonNull Intent putExtra(String name, Parcelable value) {
+ public @NonNull Intent putExtra(String name, @Nullable Parcelable value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8653,7 +8653,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getParcelableArrayExtra(String)
*/
- public @NonNull Intent putExtra(String name, Parcelable[] value) {
+ public @NonNull Intent putExtra(String name, @Nullable Parcelable[] value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8677,7 +8677,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #getParcelableArrayListExtra(String)
*/
public @NonNull Intent putParcelableArrayListExtra(String name,
- ArrayList<? extends Parcelable> value) {
+ @Nullable ArrayList<? extends Parcelable> value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8700,7 +8700,8 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getIntegerArrayListExtra(String)
*/
- public @NonNull Intent putIntegerArrayListExtra(String name, ArrayList<Integer> value) {
+ public @NonNull Intent putIntegerArrayListExtra(String name,
+ @Nullable ArrayList<Integer> value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8723,7 +8724,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getStringArrayListExtra(String)
*/
- public @NonNull Intent putStringArrayListExtra(String name, ArrayList<String> value) {
+ public @NonNull Intent putStringArrayListExtra(String name, @Nullable ArrayList<String> value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8747,7 +8748,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #getCharSequenceArrayListExtra(String)
*/
public @NonNull Intent putCharSequenceArrayListExtra(String name,
- ArrayList<CharSequence> value) {
+ @Nullable ArrayList<CharSequence> value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8770,7 +8771,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getSerializableExtra(String)
*/
- public @NonNull Intent putExtra(String name, Serializable value) {
+ public @NonNull Intent putExtra(String name, @Nullable Serializable value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8793,7 +8794,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getBooleanArrayExtra(String)
*/
- public @NonNull Intent putExtra(String name, boolean[] value) {
+ public @NonNull Intent putExtra(String name, @Nullable boolean[] value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8816,7 +8817,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getByteArrayExtra(String)
*/
- public @NonNull Intent putExtra(String name, byte[] value) {
+ public @NonNull Intent putExtra(String name, @Nullable byte[] value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8839,7 +8840,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getShortArrayExtra(String)
*/
- public @NonNull Intent putExtra(String name, short[] value) {
+ public @NonNull Intent putExtra(String name, @Nullable short[] value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8862,7 +8863,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getCharArrayExtra(String)
*/
- public @NonNull Intent putExtra(String name, char[] value) {
+ public @NonNull Intent putExtra(String name, @Nullable char[] value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8885,7 +8886,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getIntArrayExtra(String)
*/
- public @NonNull Intent putExtra(String name, int[] value) {
+ public @NonNull Intent putExtra(String name, @Nullable int[] value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8908,7 +8909,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getLongArrayExtra(String)
*/
- public @NonNull Intent putExtra(String name, long[] value) {
+ public @NonNull Intent putExtra(String name, @Nullable long[] value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8931,7 +8932,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getFloatArrayExtra(String)
*/
- public @NonNull Intent putExtra(String name, float[] value) {
+ public @NonNull Intent putExtra(String name, @Nullable float[] value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8954,7 +8955,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getDoubleArrayExtra(String)
*/
- public @NonNull Intent putExtra(String name, double[] value) {
+ public @NonNull Intent putExtra(String name, @Nullable double[] value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -8977,7 +8978,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getStringArrayExtra(String)
*/
- public @NonNull Intent putExtra(String name, String[] value) {
+ public @NonNull Intent putExtra(String name, @Nullable String[] value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -9000,7 +9001,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getCharSequenceArrayExtra(String)
*/
- public @NonNull Intent putExtra(String name, CharSequence[] value) {
+ public @NonNull Intent putExtra(String name, @Nullable CharSequence[] value) {
if (mExtras == null) {
mExtras = new Bundle();
}
@@ -9023,7 +9024,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #removeExtra
* @see #getBundleExtra(String)
*/
- public @NonNull Intent putExtra(String name, Bundle value) {
+ public @NonNull Intent putExtra(String name, @Nullable Bundle value) {
if (mExtras == null) {
mExtras = new Bundle();
}
diff --git a/core/java/android/content/MimeTypeFilter.java b/core/java/android/content/MimeTypeFilter.java
new file mode 100644
index 000000000000..1c26fd917f76
--- /dev/null
+++ b/core/java/android/content/MimeTypeFilter.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.util.ArrayList;
+
+/**
+ * Provides utility methods for matching MIME type filters used in ContentProvider.
+ *
+ * <p>Wildcards are allowed only instead of the entire type or subtype with a tree prefix.
+ * Eg. image\/*, *\/* is a valid filter and will match image/jpeg, but image/j* is invalid and
+ * it will not match image/jpeg. Suffixes and parameters are not supported, and they are treated
+ * as part of the subtype during matching. Neither type nor subtype can be empty.
+ *
+ * <p><em>Note: MIME type matching in the Android framework is case-sensitive, unlike the formal
+ * RFC definitions. As a result, you should always write these elements with lower case letters,
+ * or use {@link android.content.Intent#normalizeMimeType} to ensure that they are converted to
+ * lower case.</em>
+ *
+ * <p>MIME types can be null or ill-formatted. In such case they won't match anything.
+ *
+ * <p>MIME type filters must be correctly formatted, or an exception will be thrown.
+ * Copied from support library.
+ * {@hide}
+ */
+public final class MimeTypeFilter {
+
+ private MimeTypeFilter() {
+ }
+
+ private static boolean mimeTypeAgainstFilter(
+ @NonNull String[] mimeTypeParts, @NonNull String[] filterParts) {
+ if (filterParts.length != 2) {
+ throw new IllegalArgumentException(
+ "Ill-formatted MIME type filter. Must be type/subtype.");
+ }
+ if (filterParts[0].isEmpty() || filterParts[1].isEmpty()) {
+ throw new IllegalArgumentException(
+ "Ill-formatted MIME type filter. Type or subtype empty.");
+ }
+ if (mimeTypeParts.length != 2) {
+ return false;
+ }
+ if (!"*".equals(filterParts[0])
+ && !filterParts[0].equals(mimeTypeParts[0])) {
+ return false;
+ }
+ if (!"*".equals(filterParts[1])
+ && !filterParts[1].equals(mimeTypeParts[1])) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Matches one nullable MIME type against one MIME type filter.
+ * @return True if the {@code mimeType} matches the {@code filter}.
+ */
+ public static boolean matches(@Nullable String mimeType, @NonNull String filter) {
+ if (mimeType == null) {
+ return false;
+ }
+
+ final String[] mimeTypeParts = mimeType.split("/");
+ final String[] filterParts = filter.split("/");
+
+ return mimeTypeAgainstFilter(mimeTypeParts, filterParts);
+ }
+
+ /**
+ * Matches one nullable MIME type against an array of MIME type filters.
+ * @return The first matching filter, or null if nothing matches.
+ */
+ @Nullable
+ public static String matches(
+ @Nullable String mimeType, @NonNull String[] filters) {
+ if (mimeType == null) {
+ return null;
+ }
+
+ final String[] mimeTypeParts = mimeType.split("/");
+ for (String filter : filters) {
+ final String[] filterParts = filter.split("/");
+ if (mimeTypeAgainstFilter(mimeTypeParts, filterParts)) {
+ return filter;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Matches multiple MIME types against an array of MIME type filters.
+ * @return The first matching MIME type, or null if nothing matches.
+ */
+ @Nullable
+ public static String matches(
+ @Nullable String[] mimeTypes, @NonNull String filter) {
+ if (mimeTypes == null) {
+ return null;
+ }
+
+ final String[] filterParts = filter.split("/");
+ for (String mimeType : mimeTypes) {
+ final String[] mimeTypeParts = mimeType.split("/");
+ if (mimeTypeAgainstFilter(mimeTypeParts, filterParts)) {
+ return mimeType;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Matches multiple MIME types against an array of MIME type filters.
+ * @return The list of matching MIME types, or empty array if nothing matches.
+ */
+ @NonNull
+ public static String[] matchesMany(
+ @Nullable String[] mimeTypes, @NonNull String filter) {
+ if (mimeTypes == null) {
+ return new String[] {};
+ }
+
+ final ArrayList<String> list = new ArrayList<>();
+ final String[] filterParts = filter.split("/");
+ for (String mimeType : mimeTypes) {
+ final String[] mimeTypeParts = mimeType.split("/");
+ if (mimeTypeAgainstFilter(mimeTypeParts, filterParts)) {
+ list.add(mimeType);
+ }
+ }
+
+ return list.toArray(new String[list.size()]);
+ }
+}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index a87ee572b6d0..d0eff2e0fda9 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -276,6 +276,8 @@ interface IPackageManager {
in PersistableBundle appExtras, in PersistableBundle launcherExtras,
in SuspendDialogInfo dialogInfo, String callingPackage, int userId);
+ boolean canSuspendPackageForUser(String packageName, int userId);
+
boolean isPackageSuspendedForUser(String packageName, int userId);
PersistableBundle getSuspendedPackageAppExtras(String packageName, int userId);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index d3e40452d9fb..e14b17e5cdd3 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5797,6 +5797,30 @@ public abstract class PackageManager {
}
/**
+ * Returns whether or not a given package can be suspended via a call to {@link
+ * #setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle,
+ * SuspendDialogInfo) setPackagesSuspended}. The platform prevents suspending certain critical
+ * packages to keep the device in a functioning state, e.g. the default dialer.
+ * Apps need to hold {@link Manifest.permission#SUSPEND_APPS SUSPEND_APPS} to call this api.
+ *
+ * <p>
+ * Note that this set of critical packages can change with time, so <em>a value of {@code true}
+ * returned by this api does not guarantee that a following call to {@link
+ * #setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle,
+ * SuspendDialogInfo) setPackagesSuspended} for the same package will succeed</em>, especially
+ * if considerable time elapsed between the two calls.
+ *
+ * @param packageName The package to check.
+ * @return {@code true} if the given package can be suspended, {@code false} otherwise.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.SUSPEND_APPS)
+ public boolean canSuspendPackage(@NonNull String packageName) {
+ throw new UnsupportedOperationException("canSuspendPackage not implemented");
+ }
+
+ /**
* @see #setPackagesSuspended(String[], boolean, PersistableBundle, PersistableBundle, String)
* @param packageName The name of the package to get the suspended status of.
* @param userId The user id.
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 5f2374995775..4371c772c047 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -58,6 +58,7 @@ import java.util.HashMap;
public final class AssetManager implements AutoCloseable {
private static final String TAG = "AssetManager";
private static final boolean DEBUG_REFS = false;
+ private static final boolean FEATURE_FLAG_IDMAP2 = false;
private static final String FRAMEWORK_APK_PATH = "/system/framework/framework-res.apk";
@@ -195,13 +196,23 @@ public final class AssetManager implements AutoCloseable {
return;
}
- // Make sure that all IDMAPs are up to date.
- nativeVerifySystemIdmaps();
try {
final ArrayList<ApkAssets> apkAssets = new ArrayList<>();
apkAssets.add(ApkAssets.loadFromPath(FRAMEWORK_APK_PATH, true /*system*/));
- loadStaticRuntimeOverlays(apkAssets);
+ if (FEATURE_FLAG_IDMAP2) {
+ final String[] systemIdmapPaths =
+ nativeCreateIdmapsForStaticOverlaysTargetingAndroid();
+ if (systemIdmapPaths == null) {
+ throw new IOException("idmap2 scan failed");
+ }
+ for (String idmapPath : systemIdmapPaths) {
+ apkAssets.add(ApkAssets.loadOverlayFromPath(idmapPath, true /*system*/));
+ }
+ } else {
+ nativeVerifySystemIdmaps();
+ loadStaticRuntimeOverlays(apkAssets);
+ }
sSystemApkAssetsSet = new ArraySet<>(apkAssets);
sSystemApkAssets = apkAssets.toArray(new ApkAssets[apkAssets.size()]);
@@ -1404,6 +1415,7 @@ public final class AssetManager implements AutoCloseable {
private static native long nativeAssetGetRemainingLength(long assetPtr);
private static native void nativeVerifySystemIdmaps();
+ private static native String[] nativeCreateIdmapsForStaticOverlaysTargetingAndroid();
// Global debug native methods.
/**
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 7952c4104d1f..bd149fd05f59 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -426,6 +426,31 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
}
/**
+ * Authenticates for the given user.
+ * @param cancel An object that can be used to cancel authentication
+ * @param executor An executor to handle callback events
+ * @param callback An object to receive authentication events
+ * @param userId The user to authenticate
+ * @hide
+ */
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+ public void authenticateUser(@NonNull CancellationSignal cancel,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull AuthenticationCallback callback,
+ int userId) {
+ if (cancel == null) {
+ throw new IllegalArgumentException("Must supply a cancellation signal");
+ }
+ if (executor == null) {
+ throw new IllegalArgumentException("Must supply an executor");
+ }
+ if (callback == null) {
+ throw new IllegalArgumentException("Must supply a callback");
+ }
+ authenticateInternal(null /* crypto */, cancel, executor, callback, userId);
+ }
+
+ /**
* This call warms up the biometric hardware, displays a system-provided dialog, and starts
* scanning for a biometric. It terminates when {@link
* AuthenticationCallback#onAuthenticationError(int, CharSequence)} is called, when {@link
@@ -465,7 +490,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
if (callback == null) {
throw new IllegalArgumentException("Must supply a callback");
}
- authenticateInternal(crypto, cancel, executor, callback);
+ authenticateInternal(crypto, cancel, executor, callback, mContext.getUserId());
}
/**
@@ -502,7 +527,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
if (callback == null) {
throw new IllegalArgumentException("Must supply a callback");
}
- authenticateInternal(null /* crypto */, cancel, executor, callback);
+ authenticateInternal(null /* crypto */, cancel, executor, callback, mContext.getUserId());
}
private void cancelAuthentication() {
@@ -518,7 +543,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
private void authenticateInternal(@Nullable CryptoObject crypto,
@NonNull CancellationSignal cancel,
@NonNull @CallbackExecutor Executor executor,
- @NonNull AuthenticationCallback callback) {
+ @NonNull AuthenticationCallback callback,
+ int userId) {
try {
if (cancel.isCanceled()) {
Log.w(TAG, "Authentication already canceled");
@@ -531,7 +557,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
mExecutor = executor;
mAuthenticationCallback = callback;
final long sessionId = crypto != null ? crypto.getOpId() : 0;
- mService.authenticate(mToken, sessionId, mContext.getUserId(),
+ mService.authenticate(mToken, sessionId, userId,
mBiometricServiceReceiver, 0 /* flags */, mContext.getOpPackageName(),
mBundle, mDialogReceiver);
} catch (RemoteException e) {
diff --git a/core/java/android/hardware/display/ColorDisplayManager.java b/core/java/android/hardware/display/ColorDisplayManager.java
new file mode 100644
index 000000000000..0a76c2bc724e
--- /dev/null
+++ b/core/java/android/hardware/display/ColorDisplayManager.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.display;
+
+import android.content.Context;
+
+import com.android.internal.R;
+
+/**
+ * Manages the display's color transforms and modes.
+ * @hide
+ */
+public final class ColorDisplayManager {
+
+ /**
+ * Returns {@code true} if Night Display is supported by the device.
+ */
+ public static boolean isNightDisplayAvailable(Context context) {
+ return context.getResources().getBoolean(R.bool.config_nightDisplayAvailable);
+ }
+}
diff --git a/core/java/android/hardware/location/ContextHubClient.java b/core/java/android/hardware/location/ContextHubClient.java
index 2717c4ee5313..a83a33eac1fb 100644
--- a/core/java/android/hardware/location/ContextHubClient.java
+++ b/core/java/android/hardware/location/ContextHubClient.java
@@ -19,7 +19,6 @@ import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.PendingIntent;
-import android.content.Intent;
import android.os.RemoteException;
import com.android.internal.util.Preconditions;
@@ -49,13 +48,25 @@ public class ContextHubClient implements Closeable {
*/
private final ContextHubInfo mAttachedHub;
- private final CloseGuard mCloseGuard = CloseGuard.get();
+ private final CloseGuard mCloseGuard;
private final AtomicBoolean mIsClosed = new AtomicBoolean(false);
- /* package */ ContextHubClient(ContextHubInfo hubInfo) {
+ /*
+ * True if this is a persistent client (i.e. does not have to close the connection when the
+ * resource is freed from the system).
+ */
+ private final boolean mPersistent;
+
+ /* package */ ContextHubClient(ContextHubInfo hubInfo, boolean persistent) {
mAttachedHub = hubInfo;
- mCloseGuard.open("close");
+ mPersistent = persistent;
+ if (mPersistent) {
+ mCloseGuard = null;
+ } else {
+ mCloseGuard = CloseGuard.get();
+ mCloseGuard.open("close");
+ }
}
/**
@@ -88,11 +99,18 @@ public class ContextHubClient implements Closeable {
* Closes the connection for this client and the Context Hub Service.
*
* When this function is invoked, the messaging associated with this client is invalidated.
- * All futures messages targeted for this client are dropped at the service.
+ * All futures messages targeted for this client are dropped at the service, and the
+ * ContextHubClient is unregistered from the service.
+ *
+ * If this object has a PendingIntent, i.e. the object was generated via
+ * {@link ContextHubManager.createClient(PendingIntent, ContextHubInfo, long)}, then the
+ * Intent events corresponding to the PendingIntent will no longer be triggered.
*/
public void close() {
if (!mIsClosed.getAndSet(true)) {
- mCloseGuard.close();
+ if (mCloseGuard != null) {
+ mCloseGuard.close();
+ }
try {
mClientProxy.close();
} catch (RemoteException e) {
@@ -102,72 +120,6 @@ public class ContextHubClient implements Closeable {
}
/**
- * Registers to receive persistent intents for a given nanoapp.
- *
- * This method should be used if the caller wants to receive notifications even after the
- * process exits. The client must have an open connection with the Context Hub Service (i.e. it
- * cannot have been closed through the {@link #close()} method). Only one PendingIntent can be
- * registered at a time for a single ContextHubClient, and the PendingIntent cannot be
- * registered if already registered by a ContextHubClient. If registered successfully, intents
- * will be delivered regarding events for the specified nanoapp from the attached Context Hub.
- * Any unicast messages for this client will also be delivered. The intent will have an extra
- * {@link ContextHubManager.EXTRA_CONTEXT_HUB_INFO} of type {@link ContextHubInfo}, which
- * describes the Context Hub the intent event was for. The intent will also have an extra
- * {@link ContextHubManager.EXTRA_EVENT_TYPE} of type {@link ContextHubManager.Event}, which
- * will contain the type of the event. See {@link ContextHubManager.Event} for description of
- * each event type, along with event-specific extra fields. A client can use
- * {@link ContextHubIntentEvent.fromIntent(Intent)} to parse the Intent generated by the event.
- *
- * When the intent is received, this client can be recreated through
- * {@link ContextHubManager.createClient(PendingIntent, ContextHubInfo,
- * ContextHubClientCallback, Exectutor)}. When recreated, the client can be treated as the
- * same endpoint entity from a nanoapp's perspective, and can be continued to be used to send
- * messages even if the original process has exited.
- *
- * Intents will be delivered until it is unregistered through
- * {@link #unregisterIntent(PendingIntent)}. Note that the registration of this client will
- * continued to be maintained at the Context Hub Service until
- * {@link #unregisterIntent(PendingIntent)} is called for registered intents.
- *
- * @param pendingIntent the PendingIntent to register for this client
- * @param nanoAppId the unique ID of the nanoapp to receive events for
- * @return true on success, false otherwise
- *
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
- public boolean registerIntent(@NonNull PendingIntent pendingIntent, long nanoAppId) {
- Preconditions.checkNotNull(pendingIntent, "PendingIntent cannot be null");
-
- try {
- return mClientProxy.registerIntent(pendingIntent, nanoAppId);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Unregisters an intent previously registered via {@link #registerIntent(PendingIntent, long)}.
- * If this intent has not been registered for this client, this method returns false.
- *
- * @param pendingIntent the PendingIntent to unregister
- *
- * @return true on success, false otherwise
- *
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
- public boolean unregisterIntent(@NonNull PendingIntent pendingIntent) {
- Preconditions.checkNotNull(pendingIntent, "PendingIntent cannot be null");
-
- try {
- return mClientProxy.unregisterIntent(pendingIntent);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Sends a message to a nanoapp through the Context Hub Service.
*
* This function returns RESULT_SUCCESS if the message has reached the HAL, but
@@ -200,7 +152,9 @@ public class ContextHubClient implements Closeable {
if (mCloseGuard != null) {
mCloseGuard.warnIfOpen();
}
- close();
+ if (!mPersistent) {
+ close();
+ }
} finally {
super.finalize();
}
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 9acefa567ed6..843db6653927 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -25,6 +25,7 @@ import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.app.PendingIntent;
import android.content.Context;
+import android.content.Intent;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
@@ -757,7 +758,7 @@ public final class ContextHubManager {
Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
Preconditions.checkNotNull(executor, "Executor cannot be null");
- ContextHubClient client = new ContextHubClient(hubInfo);
+ ContextHubClient client = new ContextHubClient(hubInfo, false /* persistent */);
IContextHubClientCallback clientInterface = createClientCallback(
client, callback, executor);
@@ -793,43 +794,55 @@ public final class ContextHubManager {
}
/**
- * Creates a ContextHubClient based on an Intent received by the Context Hub Service.
+ * Creates a ContextHubClient that will receive notifications based on Intent events.
+ *
+ * This method should be used instead of {@link #createClient(ContextHubInfo,
+ * ContextHubClientCallback)} and the equivalent API if the caller wants to preserve the
+ * messaging endpoint of a ContextHubClient, even after a process exits. If the PendingIntent
+ * with the provided nanoapp has already been registered at the service previously, then the
+ * same ContextHubClient will be regenerated without creating a new client connection at the
+ * service. Note that the PendingIntent, nanoapp, and Context Hub must all match in identifying
+ * a previously registered ContextHubClient. If a client is regenerated, it can be treated as
+ * the same endpoint entity from a nanoapp's perspective, and can be continued to be
+ * used to send messages even if the original process has exited.
+ *
+ * If registered successfully, intents will be delivered regarding events or messages from the
+ * specified nanoapp from the attached Context Hub. The intent will have an extra
+ * {@link ContextHubManager.EXTRA_CONTEXT_HUB_INFO} of type {@link ContextHubInfo}, which
+ * describes the Context Hub the intent event was for. The intent will also have an extra
+ * {@link ContextHubManager.EXTRA_EVENT_TYPE} of type {@link ContextHubManager.Event}, which
+ * will contain the type of the event. See {@link ContextHubManager.Event} for description of
+ * each event type, along with event-specific extra fields. The client can also use
+ * {@link ContextHubIntentEvent.fromIntent(Intent)} to parse the Intent generated by the event.
+ *
+ * Intent events will be delivered until it is unregistered through
+ * {@link ContextHubClient.close()}. Note that the registration of this
+ * ContextHubClient at the Context Hub Service will continued to be maintained until
+ * {@link ContextHubClient.close()} is called.
*
- * This method is intended to be used after receiving an Intent received as a result of
- * {@link ContextHubClient.registerIntent(PendingIntent, long)}, and must have been created
- * through {@link #createClient(ContextHubInfo, ContextHubClientCallback, Executor)} or
- * equivalent at an earlier time.
- *
- * @param pendingIntent the PendingIntent that has been registered with a client
* @param hubInfo the hub to attach this client to
- * @param callback the notification callback to register
- * @param executor the executor to invoke the callback
+ * @param pendingIntent the PendingIntent to register to the client
+ * @param nanoAppId the ID of the nanoapp that Intent events will be generated for
* @return the registered client object
*
- * @throws IllegalArgumentException if hubInfo does not represent a valid hub, or pendingIntent
- * was not associated with a client
- * @throws IllegalStateException if the client is already registered to a valid callback
- * @throws NullPointerException if pendingIntent, hubInfo, callback, or executor is null
+ * @throws IllegalArgumentException if hubInfo does not represent a valid hub
+ * @throws IllegalStateException if there were too many registered clients at the service
+ * @throws NullPointerException if pendingIntent or hubInfo is null
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
@NonNull public ContextHubClient createClient(
- @NonNull PendingIntent pendingIntent, @NonNull ContextHubInfo hubInfo,
- @NonNull ContextHubClientCallback callback,
- @NonNull @CallbackExecutor Executor executor) {
- Preconditions.checkNotNull(pendingIntent, "PendingIntent cannot be null");
- Preconditions.checkNotNull(callback, "Callback cannot be null");
- Preconditions.checkNotNull(hubInfo, "ContextHubInfo cannot be null");
- Preconditions.checkNotNull(executor, "Executor cannot be null");
+ @NonNull ContextHubInfo hubInfo, @NonNull PendingIntent pendingIntent, long nanoAppId) {
+ Preconditions.checkNotNull(pendingIntent);
+ Preconditions.checkNotNull(hubInfo);
- ContextHubClient client = new ContextHubClient(hubInfo);
- IContextHubClientCallback clientInterface = createClientCallback(
- client, callback, executor);
+ ContextHubClient client = new ContextHubClient(hubInfo, true /* persistent */);
IContextHubClient clientProxy;
try {
- clientProxy = mService.bindClient(pendingIntent, clientInterface, hubInfo.getId());
+ clientProxy = mService.createPendingIntentClient(
+ hubInfo.getId(), pendingIntent, nanoAppId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -839,30 +852,6 @@ public final class ContextHubManager {
}
/**
- * Equivalent to {@link #createClient(PendingIntent, ContextHubInfo, ContextHubClientCallback,
- * Executor)} with the executor using the main thread's Looper.
- *
- * @param pendingIntent the PendingIntent that has been registered with a client
- * @param hubInfo the hub to attach this client to
- * @param callback the notification callback to register
- * @return the registered client object
- *
- * @throws IllegalArgumentException if hubInfo does not represent a valid hub, or pendingIntent
- * was not associated with a client
- * @throws IllegalStateException if the client is already registered to a valid callback
- * @throws NullPointerException if pendingIntent, hubInfo, or callback is null
- *
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
- @NonNull public ContextHubClient createClient(
- @NonNull PendingIntent pendingIntent, @NonNull ContextHubInfo hubInfo,
- @NonNull ContextHubClientCallback callback) {
- return createClient(
- pendingIntent, hubInfo, callback, new HandlerExecutor(Handler.getMain()));
- }
-
- /**
* Unregister a callback for receive messages from the context hub.
*
* @see Callback
diff --git a/core/java/android/hardware/location/IContextHubClient.aidl b/core/java/android/hardware/location/IContextHubClient.aidl
index b53941491c24..e33545c40360 100644
--- a/core/java/android/hardware/location/IContextHubClient.aidl
+++ b/core/java/android/hardware/location/IContextHubClient.aidl
@@ -29,10 +29,4 @@ interface IContextHubClient {
// Closes the connection with the Context Hub
void close();
-
- // Registers a PendingIntent with the client
- boolean registerIntent(in PendingIntent pendingIntent, long nanoAppId);
-
- // Unregisters a PendingIntent from the client
- boolean unregisterIntent(in PendingIntent pendingIntent);
}
diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl
index 9b0acdf14724..19ed694f4a72 100644
--- a/core/java/android/hardware/location/IContextHubService.aidl
+++ b/core/java/android/hardware/location/IContextHubService.aidl
@@ -61,10 +61,9 @@ interface IContextHubService {
// Creates a client to send and receive messages
IContextHubClient createClient(in IContextHubClientCallback client, int contextHubId);
- // Binds an existing client to a new callback interface, provided a previously registered
- // PendingIntent
- IContextHubClient bindClient(
- in PendingIntent pendingIntent, in IContextHubClientCallback client, int contextHubId);
+ // Creates a PendingIntent-based client to send and receive messages
+ IContextHubClient createPendingIntentClient(
+ int contextHubId, in PendingIntent pendingIntent, long nanoAppId);
// Returns a list of ContextHub objects of available hubs
List<ContextHubInfo> getContextHubs();
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9cf7de586d17..c437dde2dacc 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2421,7 +2421,7 @@ public abstract class BatteryStats implements Parcelable {
public static final IntToString[] HISTORY_EVENT_INT_FORMATTERS = new IntToString[] {
sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
- sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
+ sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sIntToString,
sUidToString, sUidToString, sUidToString, sUidToString, sUidToString, sUidToString,
sUidToString, sUidToString, sUidToString, sIntToString
};
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 1f47f933cde9..28ea553c8800 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -1390,3 +1390,4 @@ public class FileUtils {
}
}
}
+
diff --git a/core/java/android/os/IStatsManager.aidl b/core/java/android/os/IStatsManager.aidl
index 124f2072933e..74d434c51781 100644
--- a/core/java/android/os/IStatsManager.aidl
+++ b/core/java/android/os/IStatsManager.aidl
@@ -62,12 +62,15 @@ interface IStatsManager {
* Inform statsd what the version and package are for each uid. Note that each array should
* have the same number of elements, and version[i] and package[i] correspond to uid[i].
*/
- oneway void informAllUidData(in int[] uid, in long[] version, in String[] app);
+ oneway void informAllUidData(in int[] uid, in long[] version, in String[] version_string,
+ in String[] app, in String[] installer);
/**
- * Inform statsd what the uid and version are for one app that was updated.
+ * Inform statsd what the uid, version, version_string, and installer are for one app that was
+ * updated.
*/
- oneway void informOnePackage(in String app, in int uid, in long version);
+ oneway void informOnePackage(in String app, in int uid, in long version,
+ in String version_string, in String installer);
/**
* Inform stats that an app was removed.
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 126588a3a817..44b9e311dc0b 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -1056,6 +1056,9 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
/**
* Internal class representing a remote status read by
* {@link ParcelFileDescriptor#readCommStatus(FileDescriptor, byte[])}.
+ *
+ * Warning: this must be kept in sync with ParcelFileDescriptorStatus at
+ * frameworks/native/libs/binder/Parcel.cpp
*/
private static class Status {
/** Special value indicating remote side died. */
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index a307cd80e724..1c1db68babc3 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -24,6 +24,7 @@ import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.content.Context;
+import android.service.dreams.Sandman;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
@@ -1001,6 +1002,29 @@ public final class PowerManager {
}
/**
+ * Requests the device to start dreaming.
+ * <p>
+ * If dream can not be started, for example if another {@link PowerManager} transition is in
+ * progress, does nothing. Unlike {@link #nap(long)}, this does not put device to sleep when
+ * dream ends.
+ * </p><p>
+ * Requires the {@link android.Manifest.permission#WRITE_DREAM_STATE} permission.
+ * </p>
+ *
+ * @param time The time when the request to nap was issued, in the
+ * {@link SystemClock#uptimeMillis()} time base. This timestamp may be used to correctly
+ * order the dream request with other power management functions. It should be set
+ * to the timestamp of the input event that caused the request to dream.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE)
+ public void dream(long time) {
+ Sandman.startDreamByUserRequest(mContext);
+ }
+
+ /**
* Boosts the brightness of the screen to maximum for a predetermined
* period of time. This is used to make the screen more readable in bright
* daylight for a short duration.
diff --git a/core/java/android/os/StatsLogEventWrapper.java b/core/java/android/os/StatsLogEventWrapper.java
index 72e1ab972846..866bd9a17f41 100644
--- a/core/java/android/os/StatsLogEventWrapper.java
+++ b/core/java/android/os/StatsLogEventWrapper.java
@@ -104,14 +104,6 @@ public final class StatsLogEventWrapper implements Parcelable {
}
/**
- * Write a double value.
- */
- public void writeDouble(double val) {
- mTypes.add(EVENT_TYPE_DOUBLE);
- mValues.add(val);
- }
-
- /**
* Write a storage value.
*/
public void writeStorage(byte[] val) {
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index d679fc7e619a..423ce771969f 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -268,6 +268,9 @@ public class StorageManager {
public static final int ENCRYPTION_STATE_ERROR_CORRUPT =
IVold.ENCRYPTION_STATE_ERROR_CORRUPT;
+ /** @hide Prefix used in sandboxIds for apps with sharedUserIds */
+ public static final String SHARED_SANDBOX_PREFIX = "shared-";
+
private static volatile IStorageManager sStorageManager = null;
private final Context mContext;
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 67e52aad9206..16d454dd0179 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -16,12 +16,11 @@
package android.provider;
-import static android.system.OsConstants.SEEK_SET;
-
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull;
import static com.android.internal.util.Preconditions.checkCollectionNotEmpty;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.ContentProviderClient;
@@ -29,13 +28,12 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.MimeTypeFilter;
import android.content.pm.ResolveInfo;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.graphics.ImageDecoder;
-import android.graphics.Matrix;
import android.graphics.Point;
import android.media.ExifInterface;
import android.net.Uri;
@@ -50,20 +48,13 @@ import android.os.Parcelable;
import android.os.ParcelableException;
import android.os.RemoteException;
import android.os.storage.StorageVolume;
-import android.system.ErrnoException;
-import android.system.Os;
import android.util.DataUnit;
import android.util.Log;
-import android.util.Size;
-
-import libcore.io.IoUtils;
-import java.io.BufferedInputStream;
import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -113,6 +104,54 @@ public final class DocumentsContract {
public static final String EXTRA_TARGET_URI = "android.content.extra.TARGET_URI";
/**
+ * Key for {@link DocumentsProvider} to query display name is matched.
+ * The match of display name is partial matching and case-insensitive.
+ * Ex: The value is "o", the display name of the results will contain
+ * both "foo" and "Open".
+ *
+ * @see DocumentsProvider#querySearchDocuments(String, String[],
+ * Bundle)
+ * {@hide}
+ */
+ public static final String QUERY_ARG_DISPLAY_NAME = "android:query-arg-display-name";
+
+ /**
+ * Key for {@link DocumentsProvider} to query mime types is matched.
+ * The value is a string array, it can support different mime types.
+ * Each items will be treated as "OR" condition. Ex: {"image/*" ,
+ * "video/*"}. The mime types of the results will contain both image
+ * type and video type.
+ *
+ * @see DocumentsProvider#querySearchDocuments(String, String[],
+ * Bundle)
+ * {@hide}
+ */
+ public static final String QUERY_ARG_MIME_TYPES = "android:query-arg-mime-types";
+
+ /**
+ * Key for {@link DocumentsProvider} to query the file size in bytes is
+ * larger than the value.
+ *
+ * @see DocumentsProvider#querySearchDocuments(String, String[],
+ * Bundle)
+ * {@hide}
+ */
+ public static final String QUERY_ARG_FILE_SIZE_OVER = "android:query-arg-file-size-over";
+
+ /**
+ * Key for {@link DocumentsProvider} to query the last modified time
+ * is newer than the value. The unit is in milliseconds since
+ * January 1, 1970 00:00:00.0 UTC.
+ *
+ * @see DocumentsProvider#querySearchDocuments(String, String[],
+ * Bundle)
+ * @see Document#COLUMN_LAST_MODIFIED
+ * {@hide}
+ */
+ public static final String QUERY_ARG_LAST_MODIFIED_AFTER =
+ "android:query-arg-last-modified-after";
+
+ /**
* Sets the desired initial location visible to user when file chooser is shown.
*
* <p>Applicable to {@link Intent} with actions:
@@ -929,6 +968,89 @@ public final class DocumentsContract {
}
/**
+ * Check if the values match the query arguments.
+ *
+ * @param queryArgs the query arguments
+ * @param displayName the display time to check against
+ * @param mimeType the mime type to check against
+ * @param lastModified the last modified time to check against
+ * @param size the size to check against
+ * @hide
+ */
+ public static boolean matchSearchQueryArguments(Bundle queryArgs, String displayName,
+ String mimeType, long lastModified, long size) {
+ if (queryArgs == null) {
+ return true;
+ }
+
+ final String argDisplayName = queryArgs.getString(QUERY_ARG_DISPLAY_NAME, "");
+ if (!argDisplayName.isEmpty()) {
+ // TODO (118795812) : Enhance the search string handled in DocumentsProvider
+ if (!displayName.toLowerCase().contains(argDisplayName.toLowerCase())) {
+ return false;
+ }
+ }
+
+ final long argFileSize = queryArgs.getLong(QUERY_ARG_FILE_SIZE_OVER, -1 /* defaultValue */);
+ if (argFileSize != -1 && size < argFileSize) {
+ return false;
+ }
+
+ final long argLastModified = queryArgs.getLong(QUERY_ARG_LAST_MODIFIED_AFTER,
+ -1 /* defaultValue */);
+ if (argLastModified != -1 && lastModified < argLastModified) {
+ return false;
+ }
+
+ final String[] argMimeTypes = queryArgs.getStringArray(QUERY_ARG_MIME_TYPES);
+ if (argMimeTypes != null && argMimeTypes.length > 0) {
+ mimeType = Intent.normalizeMimeType(mimeType);
+ for (String type : argMimeTypes) {
+ if (MimeTypeFilter.matches(mimeType, Intent.normalizeMimeType(type))) {
+ return true;
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Get the handled query arguments from the query bundle. The handled arguments are
+ * {@link DocumentsContract#QUERY_ARG_DISPLAY_NAME},
+ * {@link DocumentsContract#QUERY_ARG_MIME_TYPES},
+ * {@link DocumentsContract#QUERY_ARG_FILE_SIZE_OVER} and
+ * {@link DocumentsContract#QUERY_ARG_LAST_MODIFIED_AFTER}.
+ *
+ * @param queryArgs the query arguments to be parsed.
+ * @return the handled query arguments
+ * @hide
+ */
+ public static String[] getHandledQueryArguments(Bundle queryArgs) {
+ if (queryArgs == null) {
+ return new String[0];
+ }
+
+ final ArrayList<String> args = new ArrayList<>();
+ if (queryArgs.keySet().contains(QUERY_ARG_DISPLAY_NAME)) {
+ args.add(QUERY_ARG_DISPLAY_NAME);
+ }
+
+ if (queryArgs.keySet().contains(QUERY_ARG_FILE_SIZE_OVER)) {
+ args.add(QUERY_ARG_FILE_SIZE_OVER);
+ }
+
+ if (queryArgs.keySet().contains(QUERY_ARG_LAST_MODIFIED_AFTER)) {
+ args.add(QUERY_ARG_LAST_MODIFIED_AFTER);
+ }
+
+ if (queryArgs.keySet().contains(QUERY_ARG_MIME_TYPES)) {
+ args.add(QUERY_ARG_MIME_TYPES);
+ }
+ return args.toArray(new String[0]);
+ }
+
+ /**
* Test if the given URI represents a {@link Document} backed by a
* {@link DocumentsProvider}.
*
@@ -1052,6 +1174,15 @@ public final class DocumentsContract {
return searchDocumentsUri.getQueryParameter(PARAM_QUERY);
}
+ /**
+ * Extract the search query from a Bundle
+ * {@link #QUERY_ARG_DISPLAY_NAME}.
+ * {@hide}
+ */
+ public static String getSearchDocumentsQuery(@NonNull Bundle bundle) {
+ return bundle.getString(QUERY_ARG_DISPLAY_NAME, "" /* defaultValue */);
+ }
+
/** {@hide} */
@UnsupportedAppUsage
public static Uri setManageMode(Uri uri) {
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 68f8acd8a586..58f82134ec50 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -32,7 +32,6 @@ import static android.provider.DocumentsContract.buildDocumentUriMaybeUsingTree;
import static android.provider.DocumentsContract.buildTreeDocumentUri;
import static android.provider.DocumentsContract.getDocumentId;
import static android.provider.DocumentsContract.getRootId;
-import static android.provider.DocumentsContract.getSearchDocumentsQuery;
import static android.provider.DocumentsContract.getTreeDocumentId;
import static android.provider.DocumentsContract.isTreeUri;
@@ -47,6 +46,7 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.MimeTypeFilter;
import android.content.UriMatcher;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
@@ -651,6 +651,55 @@ public abstract class DocumentsProvider extends ContentProvider {
}
/**
+ * Return documents that match the given query under the requested
+ * root. The returned documents should be sorted by relevance in descending
+ * order. How documents are matched against the query string is an
+ * implementation detail left to each provider, but it's suggested that at
+ * least {@link Document#COLUMN_DISPLAY_NAME} be matched in a
+ * case-insensitive fashion.
+ * <p>
+ * If your provider is cloud-based, and you have some data cached or pinned
+ * locally, you may return the local data immediately, setting
+ * {@link DocumentsContract#EXTRA_LOADING} on the Cursor to indicate that
+ * you are still fetching additional data. Then, when the network data is
+ * available, you can send a change notification to trigger a requery and
+ * return the complete contents.
+ * <p>
+ * To support change notifications, you must
+ * {@link Cursor#setNotificationUri(ContentResolver, Uri)} with a relevant
+ * Uri, such as {@link DocumentsContract#buildSearchDocumentsUri(String,
+ * String, String)}. Then you can call {@link ContentResolver#notifyChange(Uri,
+ * android.database.ContentObserver, boolean)} with that Uri to send change
+ * notifications.
+ *
+ * @param rootId the root to search under.
+ * @param projection list of {@link Document} columns to put into the
+ * cursor. If {@code null} all supported columns should be
+ * included.
+ * @param queryArgs the query arguments.
+ * {@link DocumentsContract#QUERY_ARG_DISPLAY_NAME},
+ * {@link DocumentsContract#QUERY_ARG_MIME_TYPES},
+ * {@link DocumentsContract#QUERY_ARG_FILE_SIZE_OVER},
+ * {@link DocumentsContract#QUERY_ARG_LAST_MODIFIED_AFTER}.
+ * @return cursor containing search result. Include
+ * {@link ContentResolver#EXTRA_HONORED_ARGS} in {@link Cursor}
+ * extras {@link Bundle} when any QUERY_ARG_* value was honored
+ * during the preparation of the results.
+ *
+ * @see ContentResolver#EXTRA_HONORED_ARGS
+ * @see DocumentsContract#EXTRA_LOADING
+ * @see DocumentsContract#EXTRA_INFO
+ * @see DocumentsContract#EXTRA_ERROR
+ * {@hide}
+ */
+ @SuppressWarnings("unused")
+ public Cursor querySearchDocuments(String rootId, String[] projection, Bundle queryArgs)
+ throws FileNotFoundException {
+ return querySearchDocuments(rootId, DocumentsContract.getSearchDocumentsQuery(queryArgs),
+ projection);
+ }
+
+ /**
* Ejects the root. Throws {@link IllegalStateException} if ejection failed.
*
* @param rootId the root to be ejected.
@@ -795,7 +844,7 @@ public abstract class DocumentsProvider extends ContentProvider {
* {@link #queryDocument(String, String[])},
* {@link #queryRecentDocuments(String, String[])},
* {@link #queryRoots(String[])}, and
- * {@link #querySearchDocuments(String, String, String[])}.
+ * {@link #querySearchDocuments(String, String[], Bundle)}.
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
@@ -812,7 +861,7 @@ public abstract class DocumentsProvider extends ContentProvider {
* @see #queryRecentDocuments(String, String[], Bundle, CancellationSignal)
* @see #queryDocument(String, String[])
* @see #queryChildDocuments(String, String[], String)
- * @see #querySearchDocuments(String, String, String[])
+ * @see #querySearchDocuments(String, String[], Bundle)
*/
@Override
public final Cursor query(
@@ -825,8 +874,7 @@ public abstract class DocumentsProvider extends ContentProvider {
return queryRecentDocuments(
getRootId(uri), projection, queryArgs, cancellationSignal);
case MATCH_SEARCH:
- return querySearchDocuments(
- getRootId(uri), getSearchDocumentsQuery(uri), projection);
+ return querySearchDocuments(getRootId(uri), projection, queryArgs);
case MATCH_DOCUMENT:
case MATCH_DOCUMENT_TREE:
enforceTree(uri);
@@ -1301,7 +1349,7 @@ public abstract class DocumentsProvider extends ContentProvider {
final long flags =
cursor.getLong(cursor.getColumnIndexOrThrow(Document.COLUMN_FLAGS));
if ((flags & Document.FLAG_VIRTUAL_DOCUMENT) == 0 && mimeType != null &&
- mimeTypeMatches(mimeTypeFilter, mimeType)) {
+ MimeTypeFilter.matches(mimeType, mimeTypeFilter)) {
return new String[] { mimeType };
}
}
@@ -1354,21 +1402,4 @@ public abstract class DocumentsProvider extends ContentProvider {
// For any other yet unhandled case, let the provider subclass handle it.
return openTypedDocument(documentId, mimeTypeFilter, opts, signal);
}
-
- /**
- * @hide
- */
- public static boolean mimeTypeMatches(String filter, String test) {
- if (test == null) {
- return false;
- } else if (filter == null || "*/*".equals(filter)) {
- return true;
- } else if (filter.equals(test)) {
- return true;
- } else if (filter.endsWith("/*")) {
- return filter.regionMatches(0, test, 0, filter.indexOf('/'));
- } else {
- return false;
- }
- }
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 040222217db4..b2666482c10d 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1825,53 +1825,6 @@ public final class Settings {
})
public @interface ResetMode{}
-
- /**
- * Indicates that the user has not started setup personalization.
- * One of the possible states for {@link Secure#USER_SETUP_PERSONALIZATION_STATE}.
- *
- * @hide
- */
- @SystemApi
- public static final int USER_SETUP_PERSONALIZATION_NOT_STARTED = 0;
-
- /**
- * Indicates that the user has not yet completed setup personalization.
- * One of the possible states for {@link Secure#USER_SETUP_PERSONALIZATION_STATE}.
- *
- * @hide
- */
- @SystemApi
- public static final int USER_SETUP_PERSONALIZATION_STARTED = 1;
-
- /**
- * Indicates that the user has snoozed personalization and will complete it later.
- * One of the possible states for {@link Secure#USER_SETUP_PERSONALIZATION_STATE}.
- *
- * @hide
- */
- @SystemApi
- public static final int USER_SETUP_PERSONALIZATION_PAUSED = 2;
-
- /**
- * Indicates that the user has completed setup personalization.
- * One of the possible states for {@link Secure#USER_SETUP_PERSONALIZATION_STATE}.
- *
- * @hide
- */
- @SystemApi
- public static final int USER_SETUP_PERSONALIZATION_COMPLETE = 10;
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({
- USER_SETUP_PERSONALIZATION_NOT_STARTED,
- USER_SETUP_PERSONALIZATION_STARTED,
- USER_SETUP_PERSONALIZATION_PAUSED,
- USER_SETUP_PERSONALIZATION_COMPLETE
- })
- public @interface UserSetupPersonalization {}
-
/**
* Activity Extra: Number of certificates
* <p>
@@ -5650,6 +5603,52 @@ public final class Settings {
public static final String USER_SETUP_COMPLETE = "user_setup_complete";
/**
+ * Indicates that the user has not started setup personalization.
+ * One of the possible states for {@link #USER_SETUP_PERSONALIZATION_STATE}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int USER_SETUP_PERSONALIZATION_NOT_STARTED = 0;
+
+ /**
+ * Indicates that the user has not yet completed setup personalization.
+ * One of the possible states for {@link #USER_SETUP_PERSONALIZATION_STATE}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int USER_SETUP_PERSONALIZATION_STARTED = 1;
+
+ /**
+ * Indicates that the user has snoozed personalization and will complete it later.
+ * One of the possible states for {@link #USER_SETUP_PERSONALIZATION_STATE}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int USER_SETUP_PERSONALIZATION_PAUSED = 2;
+
+ /**
+ * Indicates that the user has completed setup personalization.
+ * One of the possible states for {@link #USER_SETUP_PERSONALIZATION_STATE}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int USER_SETUP_PERSONALIZATION_COMPLETE = 10;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ USER_SETUP_PERSONALIZATION_NOT_STARTED,
+ USER_SETUP_PERSONALIZATION_STARTED,
+ USER_SETUP_PERSONALIZATION_PAUSED,
+ USER_SETUP_PERSONALIZATION_COMPLETE
+ })
+ public @interface UserSetupPersonalization {}
+
+ /**
* Defines the user's current state of device personalization.
* The possible states are defined in {@link UserSetupPersonalization}.
*
@@ -10325,6 +10324,18 @@ public final class Settings {
private static final Validator WIFI_PNO_FREQUENCY_CULLING_ENABLED_VALIDATOR =
BOOLEAN_VALIDATOR;
+ /**
+ * Setting to enable including recency information when determining pno network priorities.
+ * Disabled by default, and setting it to 1 will enable it.
+ * The value is boolean (0 or 1).
+ * @hide
+ */
+ public static final String WIFI_PNO_RECENCY_SORTING_ENABLED =
+ "wifi_pno_recency_sorting_enabled";
+
+ private static final Validator WIFI_PNO_RECENCY_SORTING_ENABLED_VALIDATOR =
+ BOOLEAN_VALIDATOR;
+
/**
* The maximum number of times we will retry a connection to an access
* point for which we have failed in acquiring an IP address from DHCP.
@@ -12800,6 +12811,8 @@ public final class Settings {
VALIDATORS.put(DEVICE_DEMO_MODE, BOOLEAN_VALIDATOR);
VALIDATORS.put(WIFI_PNO_FREQUENCY_CULLING_ENABLED,
WIFI_PNO_FREQUENCY_CULLING_ENABLED_VALIDATOR);
+ VALIDATORS.put(WIFI_PNO_RECENCY_SORTING_ENABLED,
+ WIFI_PNO_RECENCY_SORTING_ENABLED_VALIDATOR);
}
/**
diff --git a/core/java/android/rolecontrollerservice/IRoleControllerService.aidl b/core/java/android/rolecontrollerservice/IRoleControllerService.aidl
index 0000b9f8c76c..ac5be06abff3 100644
--- a/core/java/android/rolecontrollerservice/IRoleControllerService.aidl
+++ b/core/java/android/rolecontrollerservice/IRoleControllerService.aidl
@@ -30,4 +30,6 @@ oneway interface IRoleControllerService {
in IRoleManagerCallback callback);
void onClearRoleHolders(in String roleName, in IRoleManagerCallback callback);
+
+ void onGrantDefaultRoles(in IRoleManagerCallback callback);
}
diff --git a/core/java/android/rolecontrollerservice/RoleControllerService.java b/core/java/android/rolecontrollerservice/RoleControllerService.java
index da11bca220d4..44c45bb32acd 100644
--- a/core/java/android/rolecontrollerservice/RoleControllerService.java
+++ b/core/java/android/rolecontrollerservice/RoleControllerService.java
@@ -89,6 +89,13 @@ public abstract class RoleControllerService extends Service {
RoleControllerService.this.onClearRoleHolders(roleName,
new RoleManagerCallbackDelegate(callback));
}
+
+ @Override
+ public void onGrantDefaultRoles(IRoleManagerCallback callback) {
+ Preconditions.checkNotNull(callback, "callback cannot be null");
+ RoleControllerService.this.onGrantDefaultRoles(
+ new RoleManagerCallbackDelegate(callback));
+ }
};
}
@@ -133,6 +140,16 @@ public abstract class RoleControllerService extends Service {
public abstract void onClearRoleHolders(@NonNull String roleName,
@NonNull RoleManagerCallback callback);
+ /**
+ * Called by system to grant default permissions and roles.
+ * <p>
+ * This is typically when creating a new user or upgrading either system or
+ * permission controller package
+ *
+ * @param callback the callback for whether this call is successful
+ */
+ public abstract void onGrantDefaultRoles(@NonNull RoleManagerCallback callback);
+
private static class RoleManagerCallbackDelegate implements RoleManagerCallback {
private IRoleManagerCallback mCallback;
diff --git a/core/java/android/security/keymaster/ExportResult.java b/core/java/android/security/keymaster/ExportResult.java
index c104671fc129..1ab79fbee0b6 100644
--- a/core/java/android/security/keymaster/ExportResult.java
+++ b/core/java/android/security/keymaster/ExportResult.java
@@ -28,6 +28,11 @@ public class ExportResult implements Parcelable {
public final int resultCode;
public final byte[] exportData;
+ public ExportResult(int resultCode) {
+ this.resultCode = resultCode;
+ this.exportData = new byte[0];
+ }
+
@UnsupportedAppUsage
public static final Parcelable.Creator<ExportResult> CREATOR = new
Parcelable.Creator<ExportResult>() {
diff --git a/core/java/android/security/keymaster/KeyCharacteristics.java b/core/java/android/security/keymaster/KeyCharacteristics.java
index 555863efec91..a4fe75d6d0c0 100644
--- a/core/java/android/security/keymaster/KeyCharacteristics.java
+++ b/core/java/android/security/keymaster/KeyCharacteristics.java
@@ -52,6 +52,14 @@ public class KeyCharacteristics implements Parcelable {
readFromParcel(in);
}
+ /**
+ * Makes a shallow copy of other by copying the other's references to the KeymasterArguments
+ */
+ public void shallowCopyFrom(KeyCharacteristics other) {
+ this.swEnforced = other.swEnforced;
+ this.hwEnforced = other.hwEnforced;
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/security/keymaster/KeymasterCertificateChain.java b/core/java/android/security/keymaster/KeymasterCertificateChain.java
index 243b9fe5f7c6..00a1a1c06e79 100644
--- a/core/java/android/security/keymaster/KeymasterCertificateChain.java
+++ b/core/java/android/security/keymaster/KeymasterCertificateChain.java
@@ -54,6 +54,14 @@ public class KeymasterCertificateChain implements Parcelable {
readFromParcel(in);
}
+ /**
+ * Makes a shallow copy of other by copying the reference to the certificate chain list.
+ * @param other
+ */
+ public void shallowCopyFrom(KeymasterCertificateChain other) {
+ this.mCertificates = other.mCertificates;
+ }
+
public List<byte[]> getCertificates() {
return mCertificates;
}
diff --git a/core/java/android/security/keymaster/OperationResult.java b/core/java/android/security/keymaster/OperationResult.java
index 2943211a45f5..bc4f36000b85 100644
--- a/core/java/android/security/keymaster/OperationResult.java
+++ b/core/java/android/security/keymaster/OperationResult.java
@@ -59,6 +59,10 @@ public class OperationResult implements Parcelable {
this.outParams = outParams;
}
+ public OperationResult(int resultCode) {
+ this(resultCode, null, 0, 0, null, null);
+ }
+
protected OperationResult(Parcel in) {
resultCode = in.readInt();
token = in.readStrongBinder();
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index e5fd2921227d..55044272aff5 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1270,7 +1270,13 @@ public abstract class Layout {
*/
public float getLineLeft(int line) {
final int dir = getParagraphDirection(line);
- final Alignment align = getParagraphAlignment(line);
+ Alignment align = getParagraphAlignment(line);
+ // Before Q, StaticLayout.Builder.setAlignment didn't check whether the input alignment
+ // is null. And when it is null, the old behavior is the same as ALIGN_CENTER.
+ // To keep consistency, we convert a null alignment to ALIGN_CENTER.
+ if (align == null) {
+ align = Alignment.ALIGN_CENTER;
+ }
// First convert combinations of alignment and direction settings to
// three basic cases: ALIGN_LEFT, ALIGN_RIGHT and ALIGN_CENTER.
@@ -1319,7 +1325,13 @@ public abstract class Layout {
*/
public float getLineRight(int line) {
final int dir = getParagraphDirection(line);
- final Alignment align = getParagraphAlignment(line);
+ Alignment align = getParagraphAlignment(line);
+ // Before Q, StaticLayout.Builder.setAlignment didn't check whether the input alignment
+ // is null. And when it is null, the old behavior is the same as ALIGN_CENTER.
+ // To keep consistency, we convert a null alignment to ALIGN_CENTER.
+ if (align == null) {
+ align = Alignment.ALIGN_CENTER;
+ }
final Alignment resultAlign;
switch(align) {
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
new file mode 100644
index 000000000000..03d99553f125
--- /dev/null
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.annotation.UnsupportedAppUsage;
+import android.graphics.BaseRecordingCanvas;
+import android.graphics.CanvasProperty;
+import android.graphics.Paint;
+import android.os.Build;
+
+/**
+ * This class exists temporarily to workaround broken apps
+ *
+ * b/119066174
+ *
+ * @hide
+ */
+public abstract class DisplayListCanvas extends BaseRecordingCanvas {
+
+ /** @hide */
+ protected DisplayListCanvas(long nativeCanvas) {
+ super(nativeCanvas);
+ }
+
+ /** @hide */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ public abstract void drawRoundRect(CanvasProperty<Float> left, CanvasProperty<Float> top,
+ CanvasProperty<Float> right, CanvasProperty<Float> bottom, CanvasProperty<Float> rx,
+ CanvasProperty<Float> ry, CanvasProperty<Paint> paint);
+
+ /** @hide */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ public abstract void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
+ CanvasProperty<Float> radius, CanvasProperty<Paint> paint);
+}
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 07a57fb73a0d..4b8b7f304b0f 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -58,10 +58,33 @@ oneway interface IWindow {
void dispatchGetNewSurface();
/**
- * Tell the window that it is either gaining or losing focus. Keep it up
- * to date on the current state showing navigational focus (touch mode) too.
+ * Tell the window that it is either gaining or losing focus.
+ *
+ * @param hasFocus {@code true} if window has focus, {@code false} otherwise.
+ * @param inTouchMode {@code true} if screen is in touch mode, {@code false} otherwise.
+ * @param reportToClient {@code true} when need to report to child view with
+ * {@link View#onWindowFocusChanged(boolean)}, {@code false} otherwise.
+ * <p>
+ * Note: In the previous design, there is only one window focus state tracked by
+ * WindowManagerService.
+ * For multi-display, the window focus state is tracked by each display independently.
+ * <p>
+ * It will introduce a problem if the window was already focused on one display and then
+ * switched to another display, since the window focus state on each display is independent,
+ * there is no global window focus state in WindowManagerService, so the window focus state of
+ * the former display remains unchanged.
+ * <p>
+ * When switched back to former display, some flows that rely on the global window focus state
+ * in view root will be missed due to the window focus state remaining unchanged.
+ * (i.e: Showing single IME window when switching between displays.)
+ * <p>
+ * To solve the problem, WindowManagerService tracks the top focused display change and then
+ * callbacks to the client via this method to make sure that the client side will request the
+ * IME on the top focused display, and then set {@param reportToClient} as {@code false} to
+ * ignore reporting to the application, since its focus remains unchanged on its display.
+ *
*/
- void windowFocusChanged(boolean hasFocus, boolean inTouchMode);
+ void windowFocusChanged(boolean hasFocus, boolean inTouchMode, boolean reportToClient);
void closeSystemDialogs(String reason);
diff --git a/services/core/java/com/android/server/input/InputApplicationHandle.java b/core/java/android/view/InputApplicationHandle.java
index 3cf7edcd6b2e..dc1e505ef36d 100644
--- a/services/core/java/com/android/server/input/InputApplicationHandle.java
+++ b/core/java/android/view/InputApplicationHandle.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.input;
+package android.view;
/**
* Functions as a handle for an application that can receive input.
diff --git a/core/java/android/view/InputChannel.java b/core/java/android/view/InputChannel.java
index b2dd6ac9e971..84c8e7a2221e 100644
--- a/core/java/android/view/InputChannel.java
+++ b/core/java/android/view/InputChannel.java
@@ -18,6 +18,7 @@ package android.view;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
+import android.os.IBinder;
import android.os.Parcelable;
import android.util.Slog;
@@ -50,15 +51,17 @@ public final class InputChannel implements Parcelable {
@SuppressWarnings("unused")
@UnsupportedAppUsage
private long mPtr; // used by native code
-
+
private static native InputChannel[] nativeOpenInputChannelPair(String name);
-
+
private native void nativeDispose(boolean finalized);
private native void nativeTransferTo(InputChannel other);
private native void nativeReadFromParcel(Parcel parcel);
private native void nativeWriteToParcel(Parcel parcel);
private native void nativeDup(InputChannel target);
-
+ private native IBinder nativeGetToken();
+ private native void nativeSetToken(IBinder token);
+
private native String nativeGetName();
/**
@@ -159,14 +162,22 @@ public final class InputChannel implements Parcelable {
}
nativeWriteToParcel(out);
-
+
if ((flags & PARCELABLE_WRITE_RETURN_VALUE) != 0) {
dispose();
}
}
-
+
@Override
public String toString() {
return getName();
}
+
+ public IBinder getToken() {
+ return nativeGetToken();
+ }
+
+ public void setToken(IBinder token) {
+ nativeSetToken(token);
+ }
}
diff --git a/services/core/java/com/android/server/input/InputWindowHandle.java b/core/java/android/view/InputWindowHandle.java
index bb29bf823eb8..621ee89fac45 100644
--- a/services/core/java/com/android/server/input/InputWindowHandle.java
+++ b/core/java/android/view/InputWindowHandle.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.input;
+package android.view;
import android.graphics.Region;
import android.view.IWindow;
@@ -34,9 +34,6 @@ public final class InputWindowHandle {
// The input application handle.
public final InputApplicationHandle inputApplicationHandle;
- // The window manager's window state.
- public final Object windowState;
-
// The client window.
public final IWindow clientWindow;
@@ -97,9 +94,8 @@ public final class InputWindowHandle {
private native void nativeDispose();
public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
- Object windowState, IWindow clientWindow, int displayId) {
+ IWindow clientWindow, int displayId) {
this.inputApplicationHandle = inputApplicationHandle;
- this.windowState = windowState;
this.clientWindow = clientWindow;
this.displayId = displayId;
}
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index fa30221d2a30..4a5ccdff0dd3 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -218,11 +218,6 @@ public class NotificationHeaderView extends ViewGroup {
layoutRight = end - paddingEnd;
end = layoutLeft = layoutRight - child.getMeasuredWidth();
}
- if (child == mAudiblyAlertedIcon) {
- int paddingEnd = mContentEndMargin;
- layoutRight = end - paddingEnd;
- end = layoutLeft = layoutRight - child.getMeasuredWidth();
- }
if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
int ltrLeft = layoutLeft;
layoutLeft = getWidth() - layoutRight;
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index 9d31bd16b452..78ad0dabc81a 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -293,6 +293,12 @@ public class RenderNodeAnimator extends Animator {
setTarget(canvas.mNode);
}
+ /** @hide */
+ @UnsupportedAppUsage
+ public void setTarget(DisplayListCanvas canvas) {
+ setTarget((RecordingCanvas) canvas);
+ }
+
private void setTarget(RenderNode node) {
checkMutable();
if (mTarget != null) {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 3d16eb89c41d..a7a5024cd2a6 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -153,6 +153,9 @@ public class SurfaceControl implements Parcelable {
private static native Display.HdrCapabilities nativeGetHdrCapabilities(IBinder displayToken);
+ private static native void nativeSetInputWindowInfo(long transactionObj, long nativeObject,
+ InputWindowHandle handle);
+
private final CloseGuard mCloseGuard = CloseGuard.get();
private final String mName;
@@ -1459,6 +1462,12 @@ public class SurfaceControl implements Parcelable {
return this;
}
+ public Transaction setInputWindowInfo(SurfaceControl sc, InputWindowHandle handle) {
+ sc.checkNotReleased();
+ nativeSetInputWindowInfo(mNativeObject, sc.mNativeObject, handle);
+ return this;
+ }
+
@UnsupportedAppUsage
public Transaction setMatrix(SurfaceControl sc,
float dsdx, float dtdx, float dtdy, float dsdy) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ec16828265fc..5f1336f903d6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3406,18 +3406,33 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private static final int PFLAG4_NOTIFIED_CONTENT_CAPTURE_ADDED = 0x20;
private static final int PFLAG4_LAST_CONTENT_CAPTURE_NOTIFICATION_TYPE = 0x40;
+ /* End of masks for mPrivateFlags4 */
+
private static final int CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED = 1;
private static final int CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED = 0;
- /** @hide */
@IntDef(flag = true, prefix = { "CONTENT_CAPTURE_NOTIFICATION_TYPE_" }, value = {
CONTENT_CAPTURE_NOTIFICATION_TYPE_APPEARED,
CONTENT_CAPTURE_NOTIFICATION_TYPE_DISAPPEARED
})
@Retention(RetentionPolicy.SOURCE)
- public @interface ContentCaptureNotificationType {}
+ private @interface ContentCaptureNotificationType {}
- /* End of masks for mPrivateFlags4 */
+ /** @hide */
+ protected static final int VIEW_STRUCTURE_FOR_ASSIST = 0;
+ /** @hide */
+ protected static final int VIEW_STRUCTURE_FOR_AUTOFILL = 1;
+ /** @hide */
+ protected static final int VIEW_STRUCTURE_FOR_CONTENT_CAPTURE = 2;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = { "VIEW_STRUCTURE_FOR" }, value = {
+ VIEW_STRUCTURE_FOR_ASSIST,
+ VIEW_STRUCTURE_FOR_AUTOFILL,
+ VIEW_STRUCTURE_FOR_CONTENT_CAPTURE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ViewStructureType {}
/**
* Always allow a user to over-scroll this view, provided it is a
@@ -4717,6 +4732,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private TouchDelegate mTouchDelegate = null;
/**
+ * While touch exploration is in use, set to true when hovering across boundaries and
+ * inside the touch area of the delegate at receiving {@link MotionEvent#ACTION_HOVER_ENTER}
+ * or {@link MotionEvent#ACTION_HOVER_MOVE}. False when leaving boundaries or receiving a
+ * {@link MotionEvent#ACTION_HOVER_EXIT}.
+ * Note that children of view group are excluded in the touch area.
+ * @see #dispatchTouchExplorationHoverEvent
+ */
+ private boolean mHoveringTouchDelegate = false;
+
+ /**
* Solid color to use as a background when creating the drawing cache. Enables
* the cache to use 16 bit bitmaps instead of 32 bit.
*/
@@ -8043,8 +8068,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* fills in all data that can be inferred from the view itself.
*/
public void onProvideStructure(ViewStructure structure) {
- onProvideStructureForAssistOrAutofillOrViewCapture(structure, /* forAutofill = */ false,
- /* forViewCapture= */ false, /* flags= */ 0);
+ onProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
}
/**
@@ -8117,8 +8141,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
*/
public void onProvideAutofillStructure(ViewStructure structure, @AutofillFlags int flags) {
- onProvideStructureForAssistOrAutofillOrViewCapture(structure, /* forAutofill = */ true,
- /* forViewCapture= */ false, flags);
+ onProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
}
/**
@@ -8150,13 +8173,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* virtual views are rendered.
*/
public boolean onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
- onProvideStructureForAssistOrAutofillOrViewCapture(structure, /* forAutofill = */ false,
- /* forViewCapture= */ true, flags);
+ onProvideStructure(structure, VIEW_STRUCTURE_FOR_CONTENT_CAPTURE, flags);
return true;
}
- private void onProvideStructureForAssistOrAutofillOrViewCapture(ViewStructure structure,
- boolean forAutofill, boolean forViewCapture, @AutofillFlags int flags) {
+ /** @hide */
+ protected void onProvideStructure(@NonNull ViewStructure structure,
+ @ViewStructureType int viewFor, int flags) {
final int id = mID;
if (id != NO_ID && !isViewIdGenerated(id)) {
String pkg, type, entry;
@@ -8172,11 +8195,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
} else {
structure.setId(id, null, null, null);
}
- if (forViewCapture) {
+ if (viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+ //TODO(b/111276913): STOPSHIP - don't set it if not needed
structure.setDataIsSensitive(false);
}
- if (forAutofill || forViewCapture) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+ || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
final @AutofillType int autofillType = getAutofillType();
// Don't need to fill autofill info if view does not support it.
// For example, only TextViews that are editable support autofill
@@ -8190,7 +8215,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
int ignoredParentLeft = 0;
int ignoredParentTop = 0;
- if (forAutofill && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+ && (flags & AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 0) {
View parentGroup = null;
ViewParent viewParent = getParent();
@@ -8213,7 +8239,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY,
mRight - mLeft, mBottom - mTop);
- if (!forAutofill) {
+ if (viewFor == VIEW_STRUCTURE_FOR_ASSIST
+ || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
if (!hasIdentityMatrix()) {
structure.setTransformation(getMatrix());
}
@@ -8907,10 +8934,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * Helper used to notify the {@link IntelligenceManager}anager when the view is removed or
+ * Helper used to notify the {@link IntelligenceManager} when the view is removed or
* added, based on whether it's laid out and visible, and without knowing if the parent removed
- * it from the view
- * hierarchy.
+ * it from the view hierarchy.
*/
// TODO(b/111276913): make sure the current algorithm covers all cases. For example, it should
// probably be called every time notifyEnterOrExitForAutoFillIfNeeded() is called as well.
@@ -9084,7 +9110,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* {@link #onProvideVirtualStructure}.
*/
public void dispatchProvideStructure(ViewStructure structure) {
- dispatchProvideStructureForAssistOrAutofill(structure, false, 0);
+ dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_ASSIST, /* flags= */ 0);
}
/**
@@ -9126,12 +9152,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void dispatchProvideAutofillStructure(@NonNull ViewStructure structure,
@AutofillFlags int flags) {
- dispatchProvideStructureForAssistOrAutofill(structure, true, flags);
+ dispatchProvideStructure(structure, VIEW_STRUCTURE_FOR_AUTOFILL, flags);
}
- private void dispatchProvideStructureForAssistOrAutofill(ViewStructure structure,
- boolean forAutofill, @AutofillFlags int flags) {
- if (forAutofill) {
+ private void dispatchProvideStructure(@NonNull ViewStructure structure,
+ @ViewStructureType int viewFor, @AutofillFlags int flags) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
structure.setAutofillId(getAutofillId());
onProvideAutofillStructure(structure, flags);
onProvideAutofillVirtualStructure(structure, flags);
@@ -13949,6 +13975,96 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Dispatching hover events to {@link TouchDelegate} to improve accessibility.
+ * <p>
+ * This method is dispatching hover events to the delegate target to support explore by touch.
+ * Similar to {@link ViewGroup#dispatchTouchEvent}, this method send proper hover events to
+ * the delegate target according to the pointer and the touch area of the delegate while touch
+ * exploration enabled.
+ * </p>
+ *
+ * @param event The motion event dispatch to the delegate target.
+ * @return True if the event was handled, false otherwise.
+ *
+ * @see #onHoverEvent
+ */
+ private boolean dispatchTouchExplorationHoverEvent(MotionEvent event) {
+ final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
+ if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
+ return false;
+ }
+
+ final boolean oldHoveringTouchDelegate = mHoveringTouchDelegate;
+ final int action = event.getActionMasked();
+ boolean pointInDelegateRegion = false;
+ boolean handled = false;
+
+ final AccessibilityNodeInfo.TouchDelegateInfo info = mTouchDelegate.getTouchDelegateInfo();
+ for (int i = 0; i < info.getRegionCount(); i++) {
+ Region r = info.getRegionAt(i);
+ if (r.contains((int) event.getX(), (int) event.getY())) {
+ pointInDelegateRegion = true;
+ }
+ }
+
+ // Explore by touch should dispatch events to children under the pointer first if any
+ // before dispatching to TouchDelegate. For non-hoverable views that do not consume
+ // hover events but receive accessibility focus, it should also not delegate to these
+ // views when hovered.
+ if (!oldHoveringTouchDelegate) {
+ if ((action == MotionEvent.ACTION_HOVER_ENTER
+ || action == MotionEvent.ACTION_HOVER_MOVE)
+ && !pointInHoveredChild(event)
+ && pointInDelegateRegion) {
+ mHoveringTouchDelegate = true;
+ }
+ } else {
+ if (action == MotionEvent.ACTION_HOVER_EXIT
+ || (action == MotionEvent.ACTION_HOVER_MOVE
+ && (pointInHoveredChild(event) || !pointInDelegateRegion))) {
+ mHoveringTouchDelegate = false;
+ }
+ }
+ switch (action) {
+ case MotionEvent.ACTION_HOVER_MOVE:
+ if (oldHoveringTouchDelegate && mHoveringTouchDelegate) {
+ // Inside bounds, dispatch as is.
+ handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
+ } else if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
+ // Moving inbound, synthesize hover enter.
+ MotionEvent eventNoHistory = (event.getHistorySize() == 0)
+ ? event : MotionEvent.obtainNoHistory(event);
+ eventNoHistory.setAction(MotionEvent.ACTION_HOVER_ENTER);
+ handled = mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
+ eventNoHistory.setAction(action);
+ handled |= mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
+ } else if (oldHoveringTouchDelegate && !mHoveringTouchDelegate) {
+ // Moving outbound, synthesize hover exit.
+ final boolean hoverExitPending = event.isHoverExitPending();
+ event.setHoverExitPending(true);
+ mTouchDelegate.onTouchExplorationHoverEvent(event);
+ MotionEvent eventNoHistory = (event.getHistorySize() == 0)
+ ? event : MotionEvent.obtainNoHistory(event);
+ eventNoHistory.setHoverExitPending(hoverExitPending);
+ eventNoHistory.setAction(MotionEvent.ACTION_HOVER_EXIT);
+ mTouchDelegate.onTouchExplorationHoverEvent(eventNoHistory);
+ } // else: outside bounds, do nothing.
+ break;
+ case MotionEvent.ACTION_HOVER_ENTER:
+ if (!oldHoveringTouchDelegate && mHoveringTouchDelegate) {
+ handled = mTouchDelegate.onTouchExplorationHoverEvent(event);
+ }
+ break;
+ case MotionEvent.ACTION_HOVER_EXIT:
+ if (oldHoveringTouchDelegate) {
+ mTouchDelegate.onTouchExplorationHoverEvent(event);
+ }
+ break;
+ }
+ return handled;
+ }
+
+ /**
* Implement this method to handle hover events.
* <p>
* This method is called whenever a pointer is hovering into, over, or out of the
@@ -13985,15 +14101,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #onHoverChanged
*/
public boolean onHoverEvent(MotionEvent event) {
- // Explore by touch should dispatch events to children under pointer first if any before
- // dispatching to TouchDelegate. For children non-hoverable that will not consume events,
- // it should also not delegate when they got the pointer hovered.
- if (mTouchDelegate != null && !pointInHoveredChild(event)) {
- final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
- if (manager.isEnabled() && manager.isTouchExplorationEnabled()
- && mTouchDelegate.onTouchExplorationHoverEvent(event)) {
- return true;
- }
+ if (mTouchDelegate != null && dispatchTouchExplorationHoverEvent(event)) {
+ return true;
}
// The root view may receive hover (or touch) events that are outside the bounds of
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index a23d68b17245..7a621a318427 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2695,7 +2695,7 @@ public final class ViewRootImpl implements ViewParent,
}
}
- private void handleWindowFocusChanged() {
+ private void handleWindowFocusChanged(boolean reportToClient) {
final boolean hasWindowFocus;
final boolean inTouchMode;
synchronized (this) {
@@ -2730,8 +2730,9 @@ public final class ViewRootImpl implements ViewParent,
} catch (RemoteException ex) {
}
// Retry in a bit.
- mHandler.sendMessageDelayed(mHandler.obtainMessage(
- MSG_WINDOW_FOCUS_CHANGED), 500);
+ final Message msg = mHandler.obtainMessage(MSG_WINDOW_FOCUS_CHANGED);
+ msg.arg1 = reportToClient ? 1 : 0;
+ mHandler.sendMessageDelayed(msg, 500);
return;
}
}
@@ -2748,9 +2749,15 @@ public final class ViewRootImpl implements ViewParent,
}
if (mView != null) {
mAttachInfo.mKeyDispatchState.reset();
- mView.dispatchWindowFocusChanged(hasWindowFocus);
- mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus);
-
+ // We dispatch onWindowFocusChanged to child view only when window is gaining /
+ // losing focus.
+ // If the focus is updated from top display change but window focus on the display
+ // remains unchanged, will not callback onWindowFocusChanged again since it may
+ // be redundant & can affect the state when it callbacks.
+ if (reportToClient) {
+ mView.dispatchWindowFocusChanged(hasWindowFocus);
+ mAttachInfo.mTreeObserver.dispatchOnWindowFocusChange(hasWindowFocus);
+ }
if (mAttachInfo.mTooltipHost != null) {
mAttachInfo.mTooltipHost.hideTooltip();
}
@@ -4340,7 +4347,7 @@ public final class ViewRootImpl implements ViewParent,
}
break;
case MSG_WINDOW_FOCUS_CHANGED: {
- handleWindowFocusChanged();
+ handleWindowFocusChanged(msg.arg1 != 0 /* reportToClient */);
} break;
case MSG_DIE:
doDie();
@@ -7263,7 +7270,7 @@ public final class ViewRootImpl implements ViewParent,
}
if (stage != null) {
- handleWindowFocusChanged();
+ handleWindowFocusChanged(true /* reportToClient */);
stage.deliver(q);
} else {
finishInputEvent(q);
@@ -7580,6 +7587,11 @@ public final class ViewRootImpl implements ViewParent,
}
public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
+ windowFocusChanged(hasFocus, inTouchMode, true /* reportToClient */);
+ }
+
+ public void windowFocusChanged(boolean hasFocus, boolean inTouchMode,
+ boolean reportToClient) {
synchronized (this) {
mWindowFocusChanged = true;
mUpcomingWindowFocus = hasFocus;
@@ -7587,6 +7599,7 @@ public final class ViewRootImpl implements ViewParent,
}
Message msg = Message.obtain();
msg.what = MSG_WINDOW_FOCUS_CHANGED;
+ msg.arg1 = reportToClient ? 1 : 0;
mHandler.sendMessage(msg);
}
@@ -8131,10 +8144,11 @@ public final class ViewRootImpl implements ViewParent,
}
@Override
- public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
+ public void windowFocusChanged(boolean hasFocus, boolean inTouchMode,
+ boolean reportToClient) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
- viewAncestor.windowFocusChanged(hasFocus, inTouchMode);
+ viewAncestor.windowFocusChanged(hasFocus, inTouchMode, reportToClient);
}
}
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 4a7e783ffbdb..a8debbd623f5 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -77,11 +77,17 @@ public final class WindowInsets {
CONSUMED = new WindowInsets((Insets) null, null, null, false, false, null);
}
- /** @hide */
+ /**
+ * Construct a new WindowInsets from individual insets.
+ *
+ * A {@code null} inset indicates that the respective inset is consumed.
+ *
+ * @hide
+ */
public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets, Rect stableInsets,
boolean isRound, boolean alwaysConsumeNavBar, DisplayCutout displayCutout) {
- this(Insets.of(systemWindowInsets), Insets.of(windowDecorInsets), Insets.of(stableInsets),
- isRound, alwaysConsumeNavBar, displayCutout);
+ this(insetsOrNull(systemWindowInsets), insetsOrNull(windowDecorInsets),
+ insetsOrNull(stableInsets), isRound, alwaysConsumeNavBar, displayCutout);
}
private WindowInsets(Insets systemWindowInsets, Insets windowDecorInsets,
@@ -673,6 +679,10 @@ public final class WindowInsets {
return Insets.of(newLeft, newTop, newRight, newBottom);
}
+ private static Insets insetsOrNull(Rect insets) {
+ return insets != null ? Insets.of(insets) : null;
+ }
+
/**
* @return whether system window insets have been consumed.
*/
diff --git a/core/java/android/view/intelligence/IntelligenceManager.java b/core/java/android/view/intelligence/IntelligenceManager.java
index c02fb3218a2e..b74600b678c6 100644
--- a/core/java/android/view/intelligence/IntelligenceManager.java
+++ b/core/java/android/view/intelligence/IntelligenceManager.java
@@ -86,6 +86,13 @@ public final class IntelligenceManager {
*/
public static final int STATE_ACTIVE = 2;
+ /**
+ * Session is disabled.
+ *
+ * @hide
+ */
+ public static final int STATE_DISABLED = 3;
+
private static final String BG_THREAD_NAME = "intel_svc_streamer_thread";
/**
@@ -166,13 +173,7 @@ public final class IntelligenceManager {
public void send(int resultCode, Bundle resultData)
throws RemoteException {
synchronized (mLock) {
- if (resultCode > 0) {
- mState = STATE_ACTIVE;
- } else {
- // TODO(b/111276913): handle other cases like disabled by
- // service
- resetStateLocked();
- }
+ mState = resultCode;
if (VERBOSE) {
Log.v(TAG, "onActivityStarted() result: code=" + resultCode
+ ", id=" + mId
@@ -203,9 +204,13 @@ public final class IntelligenceManager {
// Typically happens on system apps that are started before the system service
// is ready (like com.android.settings/.FallbackHome)
//TODO(b/111276913): try to ignore session while system is not ready / boot
- // not complete instead.
- Log.w(TAG, "Closing session for " + getActivityDebugNameLocked()
- + " after " + numberEvents + " delayed events");
+ // not complete instead. Similarly, the manager service should return right away
+ // when the user does not have a service set
+ if (VERBOSE) {
+ Log.v(TAG, "Closing session for " + getActivityDebugNameLocked()
+ + " after " + numberEvents + " delayed events and state "
+ + getStateAsString(mState));
+ }
// TODO(b/111276913): blacklist activity / use special flag to indicate that
// when it's launched again
resetStateLocked();
@@ -380,7 +385,7 @@ public final class IntelligenceManager {
//TODO(b/111276913): properly implement by checking if it was explicitly disabled by
// service, or if service is not set
// (and probably renamign to isEnabledLocked()
- return mService != null;
+ return mService != null && mState != STATE_DISABLED;
}
/**
@@ -509,6 +514,8 @@ public final class IntelligenceManager {
return "WAITING_FOR_SERVER";
case STATE_ACTIVE:
return "ACTIVE";
+ case STATE_DISABLED:
+ return "DISABLED";
default:
return "INVALID:" + state;
}
diff --git a/core/java/android/view/textclassifier/ModelFileManager.java b/core/java/android/view/textclassifier/ModelFileManager.java
index 896b516bbf9a..8558a462fa40 100644
--- a/core/java/android/view/textclassifier/ModelFileManager.java
+++ b/core/java/android/view/textclassifier/ModelFileManager.java
@@ -251,6 +251,9 @@ public final class ModelFileManager {
if (!mLanguageIndependent && model.mLanguageIndependent) {
return true;
}
+ if (mLanguageIndependent && !model.mLanguageIndependent) {
+ return false;
+ }
// A higher-version model is preferred.
if (mVersion > model.getVersion()) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index f343a52b365c..10937196a74f 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2695,6 +2695,11 @@ public class WebView extends AbsoluteLayout
}
@Override
+ public boolean onProvideContentCaptureStructure(ViewStructure structure, int flags) {
+ return mProvider.getViewDelegate().onProvideContentCaptureStructure(structure, flags);
+ }
+
+ @Override
public void autofill(SparseArray<AutofillValue>values) {
mProvider.getViewDelegate().autofill(values);
}
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 00e782bd5046..ceada07c715b 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -341,6 +341,12 @@ public interface WebViewProvider {
return true; // true is the default value returned by View.isVisibleToUserForAutofill()
}
+ default boolean onProvideContentCaptureStructure(
+ @SuppressWarnings("unused") android.view.ViewStructure structure,
+ @SuppressWarnings("unused") int flags) {
+ return false; // WebView provides virtual views and is responsible to notify manager
+ }
+
public AccessibilityNodeProvider getAccessibilityNodeProvider();
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info);
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index f3fe16e8a675..ddff8581d568 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -1309,13 +1309,23 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup {
@Override
public void onProvideAutofillStructure(ViewStructure structure, int flags) {
super.onProvideAutofillStructure(structure, flags);
+ }
- final Adapter adapter = getAdapter();
- if (adapter == null) return;
-
- final CharSequence[] options = adapter.getAutofillOptions();
- if (options != null) {
- structure.setAutofillOptions(options);
+ /** @hide */
+ @Override
+ protected void onProvideStructure(@NonNull ViewStructure structure,
+ @ViewStructureType int viewFor, int flags) {
+ super.onProvideStructure(structure, viewFor, flags);
+
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+ || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+ final Adapter adapter = getAdapter();
+ if (adapter == null) return;
+
+ final CharSequence[] options = adapter.getAutofillOptions();
+ if (options != null) {
+ structure.setAutofillOptions(options);
+ }
}
}
}
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index b754d84fbaf8..eb35587cb7e7 100644
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -16,302 +16,22 @@
*/
package android.widget;
-import android.annotation.UnsupportedAppUsage;
-import android.app.AlertDialog;
import android.content.Context;
-import android.content.DialogInterface;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageItemInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PermissionGroupInfo;
-import android.content.pm.PermissionInfo;
import android.graphics.drawable.Drawable;
-import android.os.Parcel;
-import android.os.UserHandle;
-import android.text.SpannableStringBuilder;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
import com.android.internal.R;
-import java.text.Collator;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
/**
- * This class contains the SecurityPermissions view implementation.
- * Initially the package's advanced or dangerous security permissions
- * are displayed under categorized
- * groups. Clicking on the additional permissions presents
- * extended information consisting of all groups and permissions.
- * To use this view define a LinearLayout or any ViewGroup and add this
- * view by instantiating AppSecurityPermissions and invoking getPermissionsView.
+ * Allows the device admin to show certain dialogs. Should be integrated into settings.
*
+ * @deprecated
* {@hide}
*/
+@Deprecated
public class AppSecurityPermissions {
- public static final int WHICH_NEW = 1<<2;
- public static final int WHICH_ALL = 0xffff;
-
- private final static String TAG = "AppSecurityPermissions";
- private final static boolean localLOGV = false;
- private final Context mContext;
- private final LayoutInflater mInflater;
- private final PackageManager mPm;
- private final Map<String, MyPermissionGroupInfo> mPermGroups
- = new HashMap<String, MyPermissionGroupInfo>();
- private final List<MyPermissionGroupInfo> mPermGroupsList
- = new ArrayList<MyPermissionGroupInfo>();
- private final PermissionGroupInfoComparator mPermGroupComparator =
- new PermissionGroupInfoComparator();
- private final PermissionInfoComparator mPermComparator = new PermissionInfoComparator();
- private final List<MyPermissionInfo> mPermsList = new ArrayList<MyPermissionInfo>();
- private final CharSequence mNewPermPrefix;
- private String mPackageName;
-
- /** @hide */
- static class MyPermissionGroupInfo extends PermissionGroupInfo {
- CharSequence mLabel;
-
- final ArrayList<MyPermissionInfo> mNewPermissions = new ArrayList<MyPermissionInfo>();
- final ArrayList<MyPermissionInfo> mAllPermissions = new ArrayList<MyPermissionInfo>();
-
- MyPermissionGroupInfo(PermissionInfo perm) {
- name = perm.packageName;
- packageName = perm.packageName;
- }
-
- MyPermissionGroupInfo(PermissionGroupInfo info) {
- super(info);
- }
-
- public Drawable loadGroupIcon(Context context, PackageManager pm) {
- if (icon != 0) {
- return loadUnbadgedIcon(pm);
- } else {
- return context.getDrawable(R.drawable.ic_perm_device_info);
- }
- }
- }
-
- /** @hide */
- private static class MyPermissionInfo extends PermissionInfo {
- CharSequence mLabel;
-
- /**
- * PackageInfo.requestedPermissionsFlags for the new package being installed.
- */
- int mNewReqFlags;
-
- /**
- * PackageInfo.requestedPermissionsFlags for the currently installed
- * package, if it is installed.
- */
- int mExistingReqFlags;
-
- /**
- * True if this should be considered a new permission.
- */
- boolean mNew;
-
- MyPermissionInfo(PermissionInfo info) {
- super(info);
- }
- }
-
- /** @hide */
- public static class PermissionItemView extends LinearLayout implements View.OnClickListener {
- MyPermissionGroupInfo mGroup;
- MyPermissionInfo mPerm;
- AlertDialog mDialog;
- private boolean mShowRevokeUI = false;
- private String mPackageName;
-
- public PermissionItemView(Context context, AttributeSet attrs) {
- super(context, attrs);
- setClickable(true);
- }
-
- public void setPermission(MyPermissionGroupInfo grp, MyPermissionInfo perm,
- boolean first, CharSequence newPermPrefix, String packageName,
- boolean showRevokeUI) {
- mGroup = grp;
- mPerm = perm;
- mShowRevokeUI = showRevokeUI;
- mPackageName = packageName;
-
- ImageView permGrpIcon = findViewById(R.id.perm_icon);
- TextView permNameView = findViewById(R.id.perm_name);
-
- PackageManager pm = getContext().getPackageManager();
- Drawable icon = null;
- if (first) {
- icon = grp.loadGroupIcon(getContext(), pm);
- }
- CharSequence label = perm.mLabel;
- if (perm.mNew && newPermPrefix != null) {
- // If this is a new permission, format it appropriately.
- SpannableStringBuilder builder = new SpannableStringBuilder();
- Parcel parcel = Parcel.obtain();
- TextUtils.writeToParcel(newPermPrefix, parcel, 0);
- parcel.setDataPosition(0);
- CharSequence newStr = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
- parcel.recycle();
- builder.append(newStr);
- builder.append(label);
- label = builder;
- }
-
- permGrpIcon.setImageDrawable(icon);
- permNameView.setText(label);
- setOnClickListener(this);
- if (localLOGV) Log.i(TAG, "Made perm item " + perm.name
- + ": " + label + " in group " + grp.name);
- }
-
- @Override
- public void onClick(View v) {
- if (mGroup != null && mPerm != null) {
- if (mDialog != null) {
- mDialog.dismiss();
- }
- PackageManager pm = getContext().getPackageManager();
- AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
- builder.setTitle(mGroup.mLabel);
- if (mPerm.descriptionRes != 0) {
- builder.setMessage(mPerm.loadDescription(pm));
- } else {
- CharSequence appName;
- try {
- ApplicationInfo app = pm.getApplicationInfo(mPerm.packageName, 0);
- appName = app.loadLabel(pm);
- } catch (NameNotFoundException e) {
- appName = mPerm.packageName;
- }
- StringBuilder sbuilder = new StringBuilder(128);
- sbuilder.append(getContext().getString(
- R.string.perms_description_app, appName));
- sbuilder.append("\n\n");
- sbuilder.append(mPerm.name);
- builder.setMessage(sbuilder.toString());
- }
- builder.setCancelable(true);
- builder.setIcon(mGroup.loadGroupIcon(getContext(), pm));
- addRevokeUIIfNecessary(builder);
- mDialog = builder.show();
- mDialog.setCanceledOnTouchOutside(true);
- }
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- if (mDialog != null) {
- mDialog.dismiss();
- }
- }
-
- private void addRevokeUIIfNecessary(AlertDialog.Builder builder) {
- if (!mShowRevokeUI) {
- return;
- }
-
- final boolean isRequired =
- ((mPerm.mExistingReqFlags & PackageInfo.REQUESTED_PERMISSION_REQUIRED) != 0);
-
- if (isRequired) {
- return;
- }
-
- DialogInterface.OnClickListener ocl = new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- PackageManager pm = getContext().getPackageManager();
- pm.revokeRuntimePermission(mPackageName, mPerm.name,
- new UserHandle(mContext.getUserId()));
- PermissionItemView.this.setVisibility(View.GONE);
- }
- };
- builder.setNegativeButton(R.string.revoke, ocl);
- builder.setPositiveButton(R.string.ok, null);
- }
- }
-
- private AppSecurityPermissions(Context context) {
- mContext = context;
- mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mPm = mContext.getPackageManager();
- // Pick up from framework resources instead.
- mNewPermPrefix = mContext.getText(R.string.perms_new_perm_prefix);
- }
-
- @UnsupportedAppUsage
- public AppSecurityPermissions(Context context, String packageName) {
- this(context);
- mPackageName = packageName;
- Set<MyPermissionInfo> permSet = new HashSet<MyPermissionInfo>();
- PackageInfo pkgInfo;
- try {
- pkgInfo = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
- } catch (NameNotFoundException e) {
- Log.w(TAG, "Couldn't retrieve permissions for package:"+packageName);
- return;
- }
- // Extract all user permissions
- if((pkgInfo.applicationInfo != null) && (pkgInfo.applicationInfo.uid != -1)) {
- getAllUsedPermissions(pkgInfo.applicationInfo.uid, permSet);
- }
- mPermsList.addAll(permSet);
- setPermissions(mPermsList);
- }
-
- public AppSecurityPermissions(Context context, PackageInfo info) {
- this(context);
- Set<MyPermissionInfo> permSet = new HashSet<MyPermissionInfo>();
- if(info == null) {
- return;
- }
- mPackageName = info.packageName;
-
- // Convert to a PackageInfo
- PackageInfo installedPkgInfo = null;
- // Get requested permissions
- if (info.requestedPermissions != null) {
- try {
- installedPkgInfo = mPm.getPackageInfo(info.packageName,
- PackageManager.GET_PERMISSIONS);
- } catch (NameNotFoundException e) {
- }
- extractPerms(info, permSet, installedPkgInfo);
- }
- // Get permissions related to shared user if any
- if (info.sharedUserId != null) {
- int sharedUid;
- try {
- sharedUid = mPm.getUidForSharedUser(info.sharedUserId);
- getAllUsedPermissions(sharedUid, permSet);
- } catch (NameNotFoundException e) {
- Log.w(TAG, "Couldn't retrieve shared user id for: " + info.packageName);
- }
- }
- // Retrieve list of permissions
- mPermsList.addAll(permSet);
- setPermissions(mPermsList);
- }
-
/**
* Utility to retrieve a view displaying a single permission. This provides
* the old UI layout for permissions; it is only here for the device admin
@@ -327,197 +47,6 @@ public class AppSecurityPermissions {
description, dangerous, icon);
}
- private void getAllUsedPermissions(int sharedUid, Set<MyPermissionInfo> permSet) {
- String sharedPkgList[] = mPm.getPackagesForUid(sharedUid);
- if(sharedPkgList == null || (sharedPkgList.length == 0)) {
- return;
- }
- for(String sharedPkg : sharedPkgList) {
- getPermissionsForPackage(sharedPkg, permSet);
- }
- }
-
- private void getPermissionsForPackage(String packageName, Set<MyPermissionInfo> permSet) {
- try {
- PackageInfo pkgInfo = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
- extractPerms(pkgInfo, permSet, pkgInfo);
- } catch (NameNotFoundException e) {
- Log.w(TAG, "Couldn't retrieve permissions for package: " + packageName);
- }
- }
-
- private void extractPerms(PackageInfo info, Set<MyPermissionInfo> permSet,
- PackageInfo installedPkgInfo) {
- String[] strList = info.requestedPermissions;
- int[] flagsList = info.requestedPermissionsFlags;
- if ((strList == null) || (strList.length == 0)) {
- return;
- }
- for (int i=0; i<strList.length; i++) {
- String permName = strList[i];
- try {
- PermissionInfo tmpPermInfo = mPm.getPermissionInfo(permName, 0);
- if (tmpPermInfo == null) {
- continue;
- }
- int existingIndex = -1;
- if (installedPkgInfo != null
- && installedPkgInfo.requestedPermissions != null) {
- for (int j=0; j<installedPkgInfo.requestedPermissions.length; j++) {
- if (permName.equals(installedPkgInfo.requestedPermissions[j])) {
- existingIndex = j;
- break;
- }
- }
- }
- final int existingFlags = existingIndex >= 0 ?
- installedPkgInfo.requestedPermissionsFlags[existingIndex] : 0;
- if (!isDisplayablePermission(tmpPermInfo, flagsList[i], existingFlags)) {
- // This is not a permission that is interesting for the user
- // to see, so skip it.
- continue;
- }
- final String origGroupName = tmpPermInfo.group;
- String groupName = origGroupName;
- if (groupName == null) {
- groupName = tmpPermInfo.packageName;
- tmpPermInfo.group = groupName;
- }
- MyPermissionGroupInfo group = mPermGroups.get(groupName);
- if (group == null) {
- PermissionGroupInfo grp = null;
- if (origGroupName != null) {
- grp = mPm.getPermissionGroupInfo(origGroupName, 0);
- }
- if (grp != null) {
- group = new MyPermissionGroupInfo(grp);
- } else {
- // We could be here either because the permission
- // didn't originally specify a group or the group it
- // gave couldn't be found. In either case, we consider
- // its group to be the permission's package name.
- tmpPermInfo.group = tmpPermInfo.packageName;
- group = mPermGroups.get(tmpPermInfo.group);
- if (group == null) {
- group = new MyPermissionGroupInfo(tmpPermInfo);
- }
- group = new MyPermissionGroupInfo(tmpPermInfo);
- }
- mPermGroups.put(tmpPermInfo.group, group);
- }
- final boolean newPerm = installedPkgInfo != null
- && (existingFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) == 0;
- MyPermissionInfo myPerm = new MyPermissionInfo(tmpPermInfo);
- myPerm.mNewReqFlags = flagsList[i];
- myPerm.mExistingReqFlags = existingFlags;
- // This is a new permission if the app is already installed and
- // doesn't currently hold this permission.
- myPerm.mNew = newPerm;
- permSet.add(myPerm);
- } catch (NameNotFoundException e) {
- Log.i(TAG, "Ignoring unknown permission:"+permName);
- }
- }
- }
-
- @UnsupportedAppUsage
- public int getPermissionCount() {
- return getPermissionCount(WHICH_ALL);
- }
-
- private List<MyPermissionInfo> getPermissionList(MyPermissionGroupInfo grp, int which) {
- if (which == WHICH_NEW) {
- return grp.mNewPermissions;
- } else {
- return grp.mAllPermissions;
- }
- }
-
- public int getPermissionCount(int which) {
- int N = 0;
- for (int i=0; i<mPermGroupsList.size(); i++) {
- N += getPermissionList(mPermGroupsList.get(i), which).size();
- }
- return N;
- }
-
- @UnsupportedAppUsage
- public View getPermissionsView() {
- return getPermissionsView(WHICH_ALL, false);
- }
-
- public View getPermissionsViewWithRevokeButtons() {
- return getPermissionsView(WHICH_ALL, true);
- }
-
- public View getPermissionsView(int which) {
- return getPermissionsView(which, false);
- }
-
- private View getPermissionsView(int which, boolean showRevokeUI) {
- LinearLayout permsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
- LinearLayout displayList = permsView.findViewById(R.id.perms_list);
- View noPermsView = permsView.findViewById(R.id.no_permissions);
-
- displayPermissions(mPermGroupsList, displayList, which, showRevokeUI);
- if (displayList.getChildCount() <= 0) {
- noPermsView.setVisibility(View.VISIBLE);
- }
-
- return permsView;
- }
-
- /**
- * Utility method that displays permissions from a map containing group name and
- * list of permission descriptions.
- */
- private void displayPermissions(List<MyPermissionGroupInfo> groups,
- LinearLayout permListView, int which, boolean showRevokeUI) {
- permListView.removeAllViews();
-
- int spacing = (int)(8*mContext.getResources().getDisplayMetrics().density);
-
- for (int i=0; i<groups.size(); i++) {
- MyPermissionGroupInfo grp = groups.get(i);
- final List<MyPermissionInfo> perms = getPermissionList(grp, which);
- for (int j=0; j<perms.size(); j++) {
- MyPermissionInfo perm = perms.get(j);
- View view = getPermissionItemView(grp, perm, j == 0,
- which != WHICH_NEW ? mNewPermPrefix : null, showRevokeUI);
- LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- if (j == 0) {
- lp.topMargin = spacing;
- }
- if (j == grp.mAllPermissions.size()-1) {
- lp.bottomMargin = spacing;
- }
- if (permListView.getChildCount() == 0) {
- lp.topMargin *= 2;
- }
- permListView.addView(view, lp);
- }
- }
- }
-
- private PermissionItemView getPermissionItemView(MyPermissionGroupInfo grp,
- MyPermissionInfo perm, boolean first, CharSequence newPermPrefix, boolean showRevokeUI) {
- return getPermissionItemView(mContext, mInflater, grp, perm, first, newPermPrefix,
- mPackageName, showRevokeUI);
- }
-
- private static PermissionItemView getPermissionItemView(Context context, LayoutInflater inflater,
- MyPermissionGroupInfo grp, MyPermissionInfo perm, boolean first,
- CharSequence newPermPrefix, String packageName, boolean showRevokeUI) {
- PermissionItemView permView = (PermissionItemView)inflater.inflate(
- (perm.flags & PermissionInfo.FLAG_COSTS_MONEY) != 0
- ? R.layout.app_permission_item_money : R.layout.app_permission_item,
- null);
- permView.setPermission(grp, perm, first, newPermPrefix, packageName, showRevokeUI);
- return permView;
- }
-
private static View getPermissionItemViewOld(Context context, LayoutInflater inflater,
CharSequence grpName, CharSequence permList, boolean dangerous, Drawable icon) {
View permView = inflater.inflate(R.layout.app_permission_item_old, null);
@@ -536,116 +65,4 @@ public class AppSecurityPermissions {
}
return permView;
}
-
- private boolean isDisplayablePermission(PermissionInfo pInfo, int newReqFlags,
- int existingReqFlags) {
- final int base = pInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
- final boolean isNormal = (base == PermissionInfo.PROTECTION_NORMAL);
-
- // We do not show normal permissions in the UI.
- if (isNormal) {
- return false;
- }
-
- final boolean isDangerous = (base == PermissionInfo.PROTECTION_DANGEROUS)
- || ((pInfo.protectionLevel&PermissionInfo.PROTECTION_FLAG_PRE23) != 0);
- final boolean isRequired =
- ((newReqFlags&PackageInfo.REQUESTED_PERMISSION_REQUIRED) != 0);
- final boolean isDevelopment =
- ((pInfo.protectionLevel&PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0);
- final boolean wasGranted =
- ((existingReqFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0);
- final boolean isGranted =
- ((newReqFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0);
-
- // Dangerous and normal permissions are always shown to the user if the permission
- // is required, or it was previously granted
- if (isDangerous && (isRequired || wasGranted || isGranted)) {
- return true;
- }
-
- // Development permissions are only shown to the user if they are already
- // granted to the app -- if we are installing an app and they are not
- // already granted, they will not be granted as part of the install.
- if (isDevelopment && wasGranted) {
- if (localLOGV) Log.i(TAG, "Special perm " + pInfo.name
- + ": protlevel=0x" + Integer.toHexString(pInfo.protectionLevel));
- return true;
- }
- return false;
- }
-
- private static class PermissionGroupInfoComparator implements Comparator<MyPermissionGroupInfo> {
- private final Collator sCollator = Collator.getInstance();
- @Override
- public final int compare(MyPermissionGroupInfo a, MyPermissionGroupInfo b) {
- return sCollator.compare(a.mLabel, b.mLabel);
- }
- }
-
- private static class PermissionInfoComparator implements Comparator<MyPermissionInfo> {
- private final Collator sCollator = Collator.getInstance();
- PermissionInfoComparator() {
- }
- public final int compare(MyPermissionInfo a, MyPermissionInfo b) {
- return sCollator.compare(a.mLabel, b.mLabel);
- }
- }
-
- private void addPermToList(List<MyPermissionInfo> permList,
- MyPermissionInfo pInfo) {
- if (pInfo.mLabel == null) {
- pInfo.mLabel = pInfo.loadSafeLabel(mPm, 20000, PackageItemInfo.SAFE_LABEL_FLAG_TRIM
- | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
- }
- int idx = Collections.binarySearch(permList, pInfo, mPermComparator);
- if(localLOGV) Log.i(TAG, "idx="+idx+", list.size="+permList.size());
- if (idx < 0) {
- idx = -idx-1;
- permList.add(idx, pInfo);
- }
- }
-
- private void setPermissions(List<MyPermissionInfo> permList) {
- if (permList != null) {
- // First pass to group permissions
- for (MyPermissionInfo pInfo : permList) {
- if(localLOGV) Log.i(TAG, "Processing permission:"+pInfo.name);
- if(!isDisplayablePermission(pInfo, pInfo.mNewReqFlags, pInfo.mExistingReqFlags)) {
- if(localLOGV) Log.i(TAG, "Permission:"+pInfo.name+" is not displayable");
- continue;
- }
- MyPermissionGroupInfo group = mPermGroups.get(pInfo.group);
- if (group != null) {
- pInfo.mLabel = pInfo.loadSafeLabel(mPm, 20000,
- PackageItemInfo.SAFE_LABEL_FLAG_TRIM
- | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
- addPermToList(group.mAllPermissions, pInfo);
- if (pInfo.mNew) {
- addPermToList(group.mNewPermissions, pInfo);
- }
- }
- }
- }
-
- for (MyPermissionGroupInfo pgrp : mPermGroups.values()) {
- if (pgrp.labelRes != 0 || pgrp.nonLocalizedLabel != null) {
- pgrp.mLabel = pgrp.loadSafeLabel(mPm, 20000, PackageItemInfo.SAFE_LABEL_FLAG_TRIM
- | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
- } else {
- ApplicationInfo app;
- try {
- app = mPm.getApplicationInfo(pgrp.packageName, 0);
- pgrp.mLabel = app.loadSafeLabel(mPm, 20000, PackageItemInfo.SAFE_LABEL_FLAG_TRIM
- | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
- } catch (NameNotFoundException e) {
- pgrp.mLabel = pgrp.loadSafeLabel(mPm, 20000,
- PackageItemInfo.SAFE_LABEL_FLAG_TRIM
- | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE);
- }
- }
- mPermGroupsList.add(pgrp);
- }
- Collections.sort(mPermGroupsList, mPermGroupComparator);
- }
}
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 8d094898d909..d35bec8d08d5 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -578,11 +578,16 @@ public abstract class CompoundButton extends Button implements Checkable {
stream.addProperty("checked", isChecked());
}
+
+ /** @hide */
@Override
- public void onProvideAutofillStructure(ViewStructure structure, int flags) {
- super.onProvideAutofillStructure(structure, flags);
+ protected void onProvideStructure(@NonNull ViewStructure structure,
+ @ViewStructureType int viewFor, int flags) {
+ super.onProvideStructure(structure, viewFor, flags);
- structure.setDataIsSensitive(!mCheckedFromResource);
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
+ structure.setDataIsSensitive(!mCheckedFromResource);
+ }
}
@Override
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index 327a5c1d2527..ab12eaccad45 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -17,6 +17,7 @@
package android.widget;
import android.annotation.IdRes;
+import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.TypedArray;
@@ -424,10 +425,15 @@ public class RadioGroup extends LinearLayout {
}
}
+ /** @hide */
@Override
- public void onProvideAutofillStructure(ViewStructure structure, int flags) {
- super.onProvideAutofillStructure(structure, flags);
- structure.setDataIsSensitive(mCheckedId != mInitialCheckedId);
+ protected void onProvideStructure(@NonNull ViewStructure structure,
+ @ViewStructureType int viewFor, int flags) {
+ super.onProvideStructure(structure, viewFor, flags);
+
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
+ structure.setDataIsSensitive(mCheckedId != mInitialCheckedId);
+ }
}
@Override
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3bdd7b8e91be..35be7669a4d8 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6076,7 +6076,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (needEditableForNotification) {
sendAfterTextChanged((Editable) text);
} else {
- notifyManagersAfterTextChanged();
+ notifyListeningManagersAfterTextChanged();
}
// SelectionModifierCursorController depends on textCanBeSelected, which depends on text
@@ -10124,13 +10124,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
- // Always notify AutoFillManager - it will return right away if autofill is disabled.
- notifyManagersAfterTextChanged();
+ notifyListeningManagersAfterTextChanged();
hideErrorIfUnchanged();
}
- private void notifyManagersAfterTextChanged() {
+ /**
+ * Notify managers (such as {@link AutofillManager} and {@link IntelligenceManager}) that are
+ * interested on text changes.
+ */
+ private void notifyListeningManagersAfterTextChanged() {
// Autofill
if (isAutofillable()) {
@@ -10911,34 +10914,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return TextView.class.getName();
}
+ /** @hide */
@Override
- public void onProvideStructure(ViewStructure structure) {
- super.onProvideStructure(structure);
- onProvideStructureForAssistOrAutofillOrViewCapture(structure, /* forAutofill = */ false,
- /* forViewCapture= */ false);
- }
-
- @Override
- public void onProvideAutofillStructure(ViewStructure structure, int flags) {
- super.onProvideAutofillStructure(structure, flags);
- onProvideStructureForAssistOrAutofillOrViewCapture(structure, /* forAutofill = */ true,
- /* forViewCapture= */ false);
- }
-
- @Override
- public boolean onProvideContentCaptureStructure(ViewStructure structure, int flags) {
- final boolean notifyManager = super.onProvideContentCaptureStructure(structure, flags);
- onProvideStructureForAssistOrAutofillOrViewCapture(structure, /* forAutofill = */ false,
- /* forViewCapture= */ true);
- return notifyManager;
- }
+ protected void onProvideStructure(@NonNull ViewStructure structure,
+ @ViewStructureType int viewFor, int flags) {
+ super.onProvideStructure(structure, viewFor, flags);
- private void onProvideStructureForAssistOrAutofillOrViewCapture(ViewStructure structure,
- boolean forAutofill, boolean forViewCapture) {
final boolean isPassword = hasPasswordTransformationMethod()
|| isPasswordInputType(getInputType());
- if (forAutofill || forViewCapture) {
- if (forAutofill) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+ || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
structure.setDataIsSensitive(!mTextSetFromXmlOrResourceId);
}
if (mTextId != ResourceId.ID_NULL) {
@@ -10953,7 +10939,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
- if (!isPassword || forAutofill || forViewCapture) {
+ if (!isPassword || viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+ || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
if (mLayout == null) {
assumeLayout();
}
@@ -10962,7 +10949,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (lineCount <= 1) {
// Simple case: this is a single line.
final CharSequence text = getText();
- if (forAutofill) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
structure.setText(text);
} else {
structure.setText(text, getSelectionStart(), getSelectionEnd());
@@ -11026,7 +11013,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
text = text.subSequence(expandedTopChar, expandedBottomChar);
}
- if (forAutofill) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) {
structure.setText(text);
} else {
structure.setText(text, selStart - expandedTopChar, selEnd - expandedTopChar);
@@ -11042,7 +11029,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
- if (!forAutofill) {
+ if (viewFor == VIEW_STRUCTURE_FOR_ASSIST
+ || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
// Extract style information that applies to the TextView as a whole.
int style = 0;
int typefaceStyle = getTypefaceStyle();
@@ -11070,7 +11058,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
structure.setTextStyle(getTextSize(), getCurrentTextColor(),
AssistStructure.ViewNode.TEXT_COLOR_UNDEFINED /* bgColor */, style);
}
- if (forAutofill || forViewCapture) {
+ if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL
+ || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) {
structure.setMinTextEms(getMinEms());
structure.setMaxTextEms(getMaxEms());
int maxLength = -1;
diff --git a/core/java/com/android/internal/app/ColorDisplayController.java b/core/java/com/android/internal/app/ColorDisplayController.java
index 75151806cfcf..213bb75e6c6c 100644
--- a/core/java/com/android/internal/app/ColorDisplayController.java
+++ b/core/java/com/android/internal/app/ColorDisplayController.java
@@ -560,13 +560,6 @@ public final class ColorDisplayController {
}
/**
- * Returns {@code true} if Night display is supported by the device.
- */
- public static boolean isAvailable(Context context) {
- return context.getResources().getBoolean(R.bool.config_nightDisplayAvailable);
- }
-
- /**
* Callback invoked whenever the Night display settings are changed.
*/
public interface Callback {
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index 81dab2f6aeef..8bc90a891352 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -389,14 +389,18 @@ public abstract class FileSystemProvider extends DocumentsProvider {
* @param query the search condition used to match file names
* @param projection projection of the returned cursor
* @param exclusion absolute file paths to exclude from result
- * @return cursor containing search result
+ * @param queryArgs the query arguments for search
+ * @return cursor containing search result. Include
+ * {@link ContentResolver#EXTRA_HONORED_ARGS} in {@link Cursor}
+ * extras {@link Bundle} when any QUERY_ARG_* value was honored
+ * during the preparation of the results.
* @throws FileNotFoundException when root folder doesn't exist or search fails
+ *
+ * @see ContentResolver#EXTRA_HONORED_ARGS
*/
protected final Cursor querySearchDocuments(
- File folder, String query, String[] projection, Set<String> exclusion)
+ File folder, String[] projection, Set<String> exclusion, Bundle queryArgs)
throws FileNotFoundException {
-
- query = query.toLowerCase();
final MatrixCursor result = new MatrixCursor(resolveProjection(projection));
final LinkedList<File> pending = new LinkedList<>();
pending.add(folder);
@@ -407,11 +411,18 @@ public abstract class FileSystemProvider extends DocumentsProvider {
pending.add(child);
}
}
- if (file.getName().toLowerCase().contains(query)
- && !exclusion.contains(file.getAbsolutePath())) {
+ if (!exclusion.contains(file.getAbsolutePath()) && matchSearchQueryArguments(file,
+ queryArgs)) {
includeFile(result, null, file);
}
}
+
+ final String[] handledQueryArgs = DocumentsContract.getHandledQueryArguments(queryArgs);
+ if (handledQueryArgs.length > 0) {
+ final Bundle extras = new Bundle();
+ extras.putStringArray(ContentResolver.EXTRA_HONORED_ARGS, handledQueryArgs);
+ result.setExtras(extras);
+ }
return result;
}
@@ -457,6 +468,34 @@ public abstract class FileSystemProvider extends DocumentsProvider {
}
}
+ /**
+ * Test if the file matches the query arguments.
+ *
+ * @param file the file to test
+ * @param queryArgs the query arguments
+ */
+ private boolean matchSearchQueryArguments(File file, Bundle queryArgs) {
+ if (file == null) {
+ return false;
+ }
+
+ final String fileMimeType;
+ final String fileName = file.getName();
+
+ if (file.isDirectory()) {
+ fileMimeType = DocumentsContract.Document.MIME_TYPE_DIR;
+ } else {
+ int dotPos = fileName.lastIndexOf('.');
+ if (dotPos < 0) {
+ return false;
+ }
+ final String extension = fileName.substring(dotPos + 1);
+ fileMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
+ }
+ return DocumentsContract.matchSearchQueryArguments(queryArgs, fileName, fileMimeType,
+ file.lastModified(), file.length());
+ }
+
private void scanFile(File visibleFile) {
final Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(visibleFile));
diff --git a/core/java/com/android/internal/os/BatterySipper.java b/core/java/com/android/internal/os/BatterySipper.java
index 0baf73cc024a..02c9542fa40d 100644
--- a/core/java/com/android/internal/os/BatterySipper.java
+++ b/core/java/com/android/internal/os/BatterySipper.java
@@ -130,6 +130,10 @@ public class BatterySipper implements Comparable<BatterySipper> {
public double wakeLockPowerMah;
public double wifiPowerMah;
+ // ****************
+ // This list must be kept current with atoms.proto (frameworks/base/cmds/statsd/src/atoms.proto)
+ // so the ordinal values (and therefore the order) must never change.
+ // ****************
public enum DrainType {
AMBIENT_DISPLAY,
@UnsupportedAppUsage
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 8f87f9193c1f..8bdb000aad0e 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -173,12 +173,13 @@ public class ZygoteInit {
}
native private static void nativePreloadAppProcessHALs();
+ native private static void nativePreloadOpenGL();
private static void preloadOpenGL() {
String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER);
if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false) &&
(driverPackageName == null || driverPackageName.isEmpty())) {
- EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
+ nativePreloadOpenGL();
}
}
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index e3490f1fba7e..137ca7f2ac27 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -16,7 +16,6 @@
package com.android.internal.view;
-import android.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
import android.hardware.input.InputManager;
import android.os.Bundle;
@@ -66,7 +65,7 @@ public class BaseIWindow extends IWindow.Stub {
}
@Override
- public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
+ public void windowFocusChanged(boolean hasFocus, boolean touchEnabled, boolean reportToClient) {
}
@Override
diff --git a/core/java/com/android/internal/widget/SubtitleView.java b/core/java/com/android/internal/widget/SubtitleView.java
index 110782896d5a..21e63c5f2ed9 100644
--- a/core/java/com/android/internal/widget/SubtitleView.java
+++ b/core/java/com/android/internal/widget/SubtitleView.java
@@ -58,7 +58,7 @@ public class SubtitleView extends View {
/** Reusable spannable string builder used for holding text. */
private final SpannableStringBuilder mText = new SpannableStringBuilder();
- private Alignment mAlignment;
+ private Alignment mAlignment = Alignment.ALIGN_CENTER;
private TextPaint mTextPaint;
private Paint mPaint;
diff --git a/core/jni/android_hardware_input_InputApplicationHandle.cpp b/core/jni/android_hardware_input_InputApplicationHandle.cpp
index 8ace8da77b2f..5887fa7a0841 100644
--- a/core/jni/android_hardware_input_InputApplicationHandle.cpp
+++ b/core/jni/android_hardware_input_InputApplicationHandle.cpp
@@ -135,13 +135,13 @@ static const JNINativeMethod gInputApplicationHandleMethods[] = {
LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
int register_android_server_InputApplicationHandle(JNIEnv* env) {
- int res = jniRegisterNativeMethods(env, "com/android/server/input/InputApplicationHandle",
+ int res = jniRegisterNativeMethods(env, "android/view/InputApplicationHandle",
gInputApplicationHandleMethods, NELEM(gInputApplicationHandleMethods));
(void) res; // Faked use when LOG_NDEBUG.
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
jclass clazz;
- FIND_CLASS(clazz, "com/android/server/input/InputApplicationHandle");
+ FIND_CLASS(clazz, "android/view/InputApplicationHandle");
GET_FIELD_ID(gInputApplicationHandleClassInfo.ptr, clazz,
"ptr", "J");
diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp
index f4829ad26aef..6ecb5de35ae1 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.cpp
+++ b/core/jni/android_hardware_input_InputWindowHandle.cpp
@@ -80,51 +80,47 @@ bool NativeInputWindowHandle::updateInfo() {
JNIEnv* env = AndroidRuntime::getJNIEnv();
jobject obj = env->NewLocalRef(mObjWeak);
if (!obj) {
- releaseInfo();
+ releaseChannel();
return false;
}
- if (!mInfo) {
- mInfo = new InputWindowInfo();
- } else {
- mInfo->touchableRegion.clear();
- }
+ mInfo.touchableRegion.clear();
jobject inputChannelObj = env->GetObjectField(obj,
gInputWindowHandleClassInfo.inputChannel);
if (inputChannelObj) {
- mInfo->inputChannel = android_view_InputChannel_getInputChannel(env, inputChannelObj);
+ mInfo.inputChannel = android_view_InputChannel_getInputChannel(env, inputChannelObj);
env->DeleteLocalRef(inputChannelObj);
} else {
- mInfo->inputChannel.clear();
+ mInfo.inputChannel.clear();
}
jstring nameObj = jstring(env->GetObjectField(obj,
gInputWindowHandleClassInfo.name));
if (nameObj) {
const char* nameStr = env->GetStringUTFChars(nameObj, NULL);
- mInfo->name = nameStr;
+ mInfo.name = nameStr;
env->ReleaseStringUTFChars(nameObj, nameStr);
env->DeleteLocalRef(nameObj);
} else {
- mInfo->name = "<null>";
+ mInfo.name = "<null>";
}
- mInfo->layoutParamsFlags = env->GetIntField(obj,
+ mInfo.layoutParamsFlags = env->GetIntField(obj,
gInputWindowHandleClassInfo.layoutParamsFlags);
- mInfo->layoutParamsType = env->GetIntField(obj,
+ mInfo.layoutParamsType = env->GetIntField(obj,
gInputWindowHandleClassInfo.layoutParamsType);
- mInfo->dispatchingTimeout = env->GetLongField(obj,
+ mInfo.dispatchingTimeout = env->GetLongField(obj,
gInputWindowHandleClassInfo.dispatchingTimeoutNanos);
- mInfo->frameLeft = env->GetIntField(obj,
+ mInfo.frameLeft = env->GetIntField(obj,
gInputWindowHandleClassInfo.frameLeft);
- mInfo->frameTop = env->GetIntField(obj,
+ mInfo.frameTop = env->GetIntField(obj,
gInputWindowHandleClassInfo.frameTop);
- mInfo->frameRight = env->GetIntField(obj,
+ mInfo.frameRight = env->GetIntField(obj,
gInputWindowHandleClassInfo.frameRight);
- mInfo->frameBottom = env->GetIntField(obj,
+ mInfo.frameBottom = env->GetIntField(obj,
gInputWindowHandleClassInfo.frameBottom);
- mInfo->scaleFactor = env->GetFloatField(obj,
+ mInfo.scaleFactor = env->GetFloatField(obj,
gInputWindowHandleClassInfo.scaleFactor);
jobject regionObj = env->GetObjectField(obj,
@@ -133,30 +129,30 @@ bool NativeInputWindowHandle::updateInfo() {
SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
for (SkRegion::Iterator it(*region); !it.done(); it.next()) {
const SkIRect& rect = it.rect();
- mInfo->addTouchableRegion(Rect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom));
+ mInfo.addTouchableRegion(Rect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom));
}
env->DeleteLocalRef(regionObj);
}
- mInfo->visible = env->GetBooleanField(obj,
+ mInfo.visible = env->GetBooleanField(obj,
gInputWindowHandleClassInfo.visible);
- mInfo->canReceiveKeys = env->GetBooleanField(obj,
+ mInfo.canReceiveKeys = env->GetBooleanField(obj,
gInputWindowHandleClassInfo.canReceiveKeys);
- mInfo->hasFocus = env->GetBooleanField(obj,
+ mInfo.hasFocus = env->GetBooleanField(obj,
gInputWindowHandleClassInfo.hasFocus);
- mInfo->hasWallpaper = env->GetBooleanField(obj,
+ mInfo.hasWallpaper = env->GetBooleanField(obj,
gInputWindowHandleClassInfo.hasWallpaper);
- mInfo->paused = env->GetBooleanField(obj,
+ mInfo.paused = env->GetBooleanField(obj,
gInputWindowHandleClassInfo.paused);
- mInfo->layer = env->GetIntField(obj,
+ mInfo.layer = env->GetIntField(obj,
gInputWindowHandleClassInfo.layer);
- mInfo->ownerPid = env->GetIntField(obj,
+ mInfo.ownerPid = env->GetIntField(obj,
gInputWindowHandleClassInfo.ownerPid);
- mInfo->ownerUid = env->GetIntField(obj,
+ mInfo.ownerUid = env->GetIntField(obj,
gInputWindowHandleClassInfo.ownerUid);
- mInfo->inputFeatures = env->GetIntField(obj,
+ mInfo.inputFeatures = env->GetIntField(obj,
gInputWindowHandleClassInfo.inputFeatures);
- mInfo->displayId = env->GetIntField(obj,
+ mInfo.displayId = env->GetIntField(obj,
gInputWindowHandleClassInfo.displayId);
env->DeleteLocalRef(obj);
@@ -225,20 +221,20 @@ static const JNINativeMethod gInputWindowHandleMethods[] = {
LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
int register_android_server_InputWindowHandle(JNIEnv* env) {
- int res = jniRegisterNativeMethods(env, "com/android/server/input/InputWindowHandle",
+ int res = jniRegisterNativeMethods(env, "android/view/InputWindowHandle",
gInputWindowHandleMethods, NELEM(gInputWindowHandleMethods));
(void) res; // Faked use when LOG_NDEBUG.
LOG_FATAL_IF(res < 0, "Unable to register native methods.");
jclass clazz;
- FIND_CLASS(clazz, "com/android/server/input/InputWindowHandle");
+ FIND_CLASS(clazz, "android/view/InputWindowHandle");
GET_FIELD_ID(gInputWindowHandleClassInfo.ptr, clazz,
"ptr", "J");
GET_FIELD_ID(gInputWindowHandleClassInfo.inputApplicationHandle,
clazz,
- "inputApplicationHandle", "Lcom/android/server/input/InputApplicationHandle;");
+ "inputApplicationHandle", "Landroid/view/InputApplicationHandle;");
GET_FIELD_ID(gInputWindowHandleClassInfo.inputChannel, clazz,
"inputChannel", "Landroid/view/InputChannel;");
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index b2d44e73d861..7b564ae162ce 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -24,9 +24,13 @@
#include <sys/system_properties.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <unistd.h>
#include <private/android_filesystem_config.h> // for AID_SYSTEM
+#include <sstream>
+#include <string>
+
#include "android-base/logging.h"
#include "android-base/properties.h"
#include "android-base/stringprintf.h"
@@ -38,6 +42,7 @@
#include "androidfw/AssetManager2.h"
#include "androidfw/AttributeResolution.h"
#include "androidfw/MutexGuard.h"
+#include "androidfw/PosixUtils.h"
#include "androidfw/ResourceTypes.h"
#include "core_jni_helpers.h"
#include "jni.h"
@@ -54,6 +59,7 @@ extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
using ::android::base::StringPrintf;
+using ::android::util::ExecuteBinary;
namespace android {
@@ -161,18 +167,20 @@ static void NativeVerifySystemIdmaps(JNIEnv* /*env*/, jclass /*clazz*/) {
argv[argc++] = AssetManager::IDMAP_DIR;
// Directories to scan for overlays: if OVERLAY_THEME_DIR_PROPERTY is defined,
- // use OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to OVERLAY_DIR.
+ // use VENDOR_OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in
+ // addition to VENDOR_OVERLAY_DIR.
std::string overlay_theme_path = base::GetProperty(AssetManager::OVERLAY_THEME_DIR_PROPERTY,
"");
if (!overlay_theme_path.empty()) {
- overlay_theme_path = std::string(AssetManager::OVERLAY_DIR) + "/" + overlay_theme_path;
+ overlay_theme_path =
+ std::string(AssetManager::VENDOR_OVERLAY_DIR) + "/" + overlay_theme_path;
if (stat(overlay_theme_path.c_str(), &st) == 0) {
argv[argc++] = overlay_theme_path.c_str();
}
}
- if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
- argv[argc++] = AssetManager::OVERLAY_DIR;
+ if (stat(AssetManager::VENDOR_OVERLAY_DIR, &st) == 0) {
+ argv[argc++] = AssetManager::VENDOR_OVERLAY_DIR;
}
if (stat(AssetManager::PRODUCT_OVERLAY_DIR, &st) == 0) {
@@ -200,6 +208,75 @@ static void NativeVerifySystemIdmaps(JNIEnv* /*env*/, jclass /*clazz*/) {
}
}
+static jobjectArray NativeCreateIdmapsForStaticOverlaysTargetingAndroid(JNIEnv* env,
+ jclass /*clazz*/) {
+ // --input-directory can be given multiple times, but idmap2 expects the directory to exist
+ std::vector<std::string> input_dirs;
+ struct stat st;
+ if (stat(AssetManager::VENDOR_OVERLAY_DIR, &st) == 0) {
+ input_dirs.push_back(AssetManager::VENDOR_OVERLAY_DIR);
+ }
+
+ if (stat(AssetManager::PRODUCT_OVERLAY_DIR, &st) == 0) {
+ input_dirs.push_back(AssetManager::PRODUCT_OVERLAY_DIR);
+ }
+
+ if (stat(AssetManager::PRODUCT_SERVICES_OVERLAY_DIR, &st) == 0) {
+ input_dirs.push_back(AssetManager::PRODUCT_SERVICES_OVERLAY_DIR);
+ }
+
+ if (input_dirs.empty()) {
+ LOG(WARNING) << "no directories for idmap2 to scan";
+ return env->NewObjectArray(0, g_stringClass, nullptr);
+ }
+
+ std::vector<std::string> argv{"/system/bin/idmap2",
+ "scan",
+ "--recursive",
+ "--target-package-name", "android",
+ "--target-apk-path", "/system/framework/framework-res.apk",
+ "--output-directory", "/data/resource-cache"};
+
+ for (const auto& dir : input_dirs) {
+ argv.push_back("--input-directory");
+ argv.push_back(dir);
+ }
+
+ const auto result = ExecuteBinary(argv);
+
+ if (!result) {
+ LOG(ERROR) << "failed to execute idmap2";
+ return nullptr;
+ }
+
+ if (result->status != 0) {
+ LOG(ERROR) << "idmap2: " << result->stderr;
+ return nullptr;
+ }
+
+ std::vector<std::string> idmap_paths;
+ std::istringstream input(result->stdout);
+ std::string path;
+ while (std::getline(input, path)) {
+ idmap_paths.push_back(path);
+ }
+
+ jobjectArray array = env->NewObjectArray(idmap_paths.size(), g_stringClass, nullptr);
+ if (array == nullptr) {
+ return nullptr;
+ }
+ for (size_t i = 0; i < idmap_paths.size(); i++) {
+ const std::string path = idmap_paths[i];
+ jstring java_string = env->NewStringUTF(path.c_str());
+ if (env->ExceptionCheck()) {
+ return nullptr;
+ }
+ env->SetObjectArrayElement(array, i, java_string);
+ env->DeleteLocalRef(java_string);
+ }
+ return array;
+}
+
static jint CopyValue(JNIEnv* env, ApkAssetsCookie cookie, const Res_value& value, uint32_t ref,
uint32_t type_spec_flags, ResTable_config* config, jobject out_typed_value) {
env->SetIntField(out_typed_value, gTypedValueOffsets.mType, value.dataType);
@@ -1405,6 +1482,8 @@ static const JNINativeMethod gAssetManagerMethods[] = {
// System/idmap related methods.
{"nativeVerifySystemIdmaps", "()V", (void*)NativeVerifySystemIdmaps},
+ {"nativeCreateIdmapsForStaticOverlaysTargetingAndroid", "()[Ljava/lang/String;",
+ (void*)NativeCreateIdmapsForStaticOverlaysTargetingAndroid},
// Global management/debug methods.
{"getGlobalAssetCount", "()I", (void*)NativeGetGlobalAssetCount},
diff --git a/core/jni/android_view_InputChannel.cpp b/core/jni/android_view_InputChannel.cpp
index 2f179078aed8..fb6be6b4c91a 100644
--- a/core/jni/android_view_InputChannel.cpp
+++ b/core/jni/android_view_InputChannel.cpp
@@ -249,6 +249,24 @@ static void android_view_InputChannel_nativeDup(JNIEnv* env, jobject obj, jobjec
}
}
+static jobject android_view_InputChannel_nativeGetToken(JNIEnv* env, jobject obj) {
+ NativeInputChannel* nativeInputChannel =
+ android_view_InputChannel_getNativeInputChannel(env, obj);
+ if (nativeInputChannel) {
+ return javaObjectForIBinder(env, nativeInputChannel->getInputChannel()->getToken());
+ }
+ return 0;
+}
+
+static void android_view_InputChannel_nativeSetToken(JNIEnv* env, jobject obj, jobject tokenObj) {
+ NativeInputChannel* nativeInputChannel =
+ android_view_InputChannel_getNativeInputChannel(env, obj);
+ sp<IBinder> token = ibinderForJavaObject(env, tokenObj);
+ if (nativeInputChannel != nullptr) {
+ nativeInputChannel->getInputChannel()->setToken(token);
+ }
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod gInputChannelMethods[] = {
@@ -267,6 +285,10 @@ static const JNINativeMethod gInputChannelMethods[] = {
(void*)android_view_InputChannel_nativeGetName },
{ "nativeDup", "(Landroid/view/InputChannel;)V",
(void*)android_view_InputChannel_nativeDup },
+ { "nativeGetToken", "()Landroid/os/IBinder;",
+ (void*)android_view_InputChannel_nativeGetToken },
+ { "nativeSetToken", "(Landroid/os/IBinder;)V",
+ (void*)android_view_InputChannel_nativeSetToken }
};
int register_android_view_InputChannel(JNIEnv* env) {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 4eda3abdd0d6..ec9c8606e8df 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -19,6 +19,7 @@
#include "android_os_Parcel.h"
#include "android_util_Binder.h"
+#include "android_hardware_input_InputWindowHandle.h"
#include "android/graphics/Bitmap.h"
#include "android/graphics/GraphicsJNI.h"
#include "android/graphics/Region.h"
@@ -324,6 +325,18 @@ static void nativeSetAlpha(JNIEnv* env, jclass clazz, jlong transactionObj,
transaction->setAlpha(ctrl, alpha);
}
+static void nativeSetInputWindowInfo(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jobject inputWindow) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
+ sp<NativeInputWindowHandle> handle = android_server_InputWindowHandle_getHandle(
+ env, inputWindow);
+ handle->updateInfo();
+
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ transaction->setInputWindowInfo(ctrl, *handle->getInfo());
+}
+
static void nativeSetColor(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jfloatArray fColor) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -930,6 +943,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeScreenshot },
{"nativeCaptureLayers", "(Landroid/os/IBinder;Landroid/graphics/Rect;F)Landroid/graphics/GraphicBuffer;",
(void*)nativeCaptureLayers },
+ {"nativeSetInputWindowInfo", "(JJLandroid/view/InputWindowHandle;)V",
+ (void*)nativeSetInputWindowInfo },
};
int register_android_view_SurfaceControl(JNIEnv* env)
diff --git a/core/jni/com_android_internal_os_ZygoteInit.cpp b/core/jni/com_android_internal_os_ZygoteInit.cpp
index 258a55c7123a..ac0e60030fc5 100644
--- a/core/jni/com_android_internal_os_ZygoteInit.cpp
+++ b/core/jni/com_android_internal_os_ZygoteInit.cpp
@@ -16,21 +16,58 @@
#define LOG_TAG "Zygote"
+#include <EGL/egl.h>
#include <ui/GraphicBufferMapper.h>
#include "core_jni_helpers.h"
namespace {
+// Shadow call stack (SCS) is a security mitigation that uses a separate stack
+// (the SCS) for return addresses. In versions of Android newer than P, the
+// compiler cooperates with the system to ensure that the SCS address is always
+// stored in register x18, as long as the app was compiled with a new enough
+// compiler and does not use features that rely on SP-HALs (this restriction is
+// because the SP-HALs might not preserve x18 due to potentially having been
+// compiled with an old compiler as a consequence of Treble; it generally means
+// that the app must be a system app without a UI). This struct is used to
+// temporarily store the address on the stack while preloading the SP-HALs, so
+// that such apps can use the same zygote as everything else.
+struct ScopedSCSExit {
+#ifdef __aarch64__
+ void* scs;
+
+ ScopedSCSExit() {
+ __asm__ __volatile__("str x18, [%0]" ::"r"(&scs));
+ }
+
+ ~ScopedSCSExit() {
+ __asm__ __volatile__("ldr x18, [%0]; str xzr, [%0]" ::"r"(&scs));
+ }
+#else
+ // Silence unused variable warnings in non-SCS builds.
+ ScopedSCSExit() {}
+ ~ScopedSCSExit() {}
+#endif
+};
+
void android_internal_os_ZygoteInit_nativePreloadAppProcessHALs(JNIEnv* env, jclass) {
+ ScopedSCSExit x;
android::GraphicBufferMapper::preloadHal();
// Add preloading here for other HALs that are (a) always passthrough, and
// (b) loaded by most app processes.
}
+void android_internal_os_ZygoteInit_nativePreloadOpenGL(JNIEnv* env, jclass) {
+ ScopedSCSExit x;
+ eglGetDisplay(EGL_DEFAULT_DISPLAY);
+}
+
const JNINativeMethod gMethods[] = {
{ "nativePreloadAppProcessHALs", "()V",
(void*)android_internal_os_ZygoteInit_nativePreloadAppProcessHALs },
+ { "nativePreloadOpenGL", "()V",
+ (void*)android_internal_os_ZygoteInit_nativePreloadOpenGL },
};
} // anonymous namespace
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 2465759a9fa5..a398e498a301 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -85,7 +85,7 @@ bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const {
// See AssetManager.cpp for more details on overlay-subdir.
static const char* kOverlayDir = "/system/vendor/overlay/";
static const char* kVendorOverlayDir = "/vendor/overlay";
- static const char* kOverlaySubdir = "/system/vendor/overlay-subdir/";
+ static const char* kVendorOverlaySubdir = "/system/vendor/overlay-subdir/";
static const char* kSystemProductOverlayDir = "/system/product/overlay/";
static const char* kProductOverlayDir = "/product/overlay";
static const char* kSystemProductServicesOverlayDir = "/system/product_services/overlay/";
@@ -93,7 +93,7 @@ bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const {
static const char* kApkSuffix = ".apk";
if ((android::base::StartsWith(path, kOverlayDir)
- || android::base::StartsWith(path, kOverlaySubdir)
+ || android::base::StartsWith(path, kVendorOverlaySubdir)
|| android::base::StartsWith(path, kVendorOverlayDir)
|| android::base::StartsWith(path, kSystemProductOverlayDir)
|| android::base::StartsWith(path, kProductOverlayDir)
diff --git a/core/proto/android/server/location/enums.proto b/core/proto/android/server/location/enums.proto
new file mode 100644
index 000000000000..b6dc58932ce7
--- /dev/null
+++ b/core/proto/android/server/location/enums.proto
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package android.server.location;
+
+option java_outer_classname = "ServerLocationProtoEnums";
+option java_multiple_files = true;
+
+// GPS Signal Quality levels,
+// primarily used by location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+enum GpsSignalQualityEnum {
+ GPS_SIGNAL_QUALITY_UNKNOWN = -1;
+ GPS_SIGNAL_QUALITY_POOR = 0;
+ GPS_SIGNAL_QUALITY_GOOD = 1;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 297687933018..62896bed05ad 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -746,7 +746,7 @@
android:description="@string/permdesc_receiveMms"
android:protectionLevel="dangerous" />
- <!-- @TestApi Allows an application to read previously received cell broadcast
+ <!-- @SystemApi @TestApi Allows an application to read previously received cell broadcast
messages and to register a content observer to get notifications when
a cell broadcast has been received and added to the database. For
emergency alerts, the database is updated immediately after the
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 4ee97316083f..433ae399c88c 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -116,17 +116,6 @@
android:contentDescription="@string/expand_button_content_description_collapsed"
/>
<ImageView
- android:id="@+id/profile_badge"
- android:layout_width="@dimen/notification_badge_size"
- android:layout_height="@dimen/notification_badge_size"
- android:layout_gravity="center"
- android:layout_marginStart="4dp"
- android:paddingTop="1dp"
- android:scaleType="fitCenter"
- android:visibility="gone"
- android:contentDescription="@string/notification_work_profile_content_description"
- />
- <ImageView
android:id="@+id/alerted_icon"
android:layout_width="@dimen/notification_alerted_size"
android:layout_height="@dimen/notification_alerted_size"
@@ -138,6 +127,17 @@
android:contentDescription="@string/notification_alerted_content_description"
android:src="@drawable/ic_notifications_alerted"
android:tint="@color/notification_secondary_text_color_light"
+ />
+ <ImageView
+ android:id="@+id/profile_badge"
+ android:layout_width="@dimen/notification_badge_size"
+ android:layout_height="@dimen/notification_badge_size"
+ android:layout_gravity="center"
+ android:layout_marginStart="4dp"
+ android:paddingTop="1dp"
+ android:scaleType="fitCenter"
+ android:visibility="gone"
+ android:contentDescription="@string/notification_work_profile_content_description"
/>
<LinearLayout
android:id="@+id/app_ops"
diff --git a/core/res/res/values-night/themes_device_defaults.xml b/core/res/res/values-night/themes_device_defaults.xml
index 931674a8c0cb..84c6446e81ce 100644
--- a/core/res/res/values-night/themes_device_defaults.xml
+++ b/core/res/res/values-night/themes_device_defaults.xml
@@ -52,6 +52,9 @@ easier.
<!-- DeviceDefault theme for a window that should look like the Settings app. -->
<style name="Theme.DeviceDefault.Settings" parent="Theme.DeviceDefault">
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
+ <item name="colorBackground">@color/primary_dark_device_default_settings</item>
+
+ <item name="listDivider">@color/list_divider_color_dark</item>
</style>
<!-- Theme for the dialog shown when an app crashes or ANRs. -->
diff --git a/core/res/res/values/colors_car.xml b/core/res/res/values/colors_car.xml
index 32671ac8f752..ea7c00919527 100644
--- a/core/res/res/values/colors_car.xml
+++ b/core/res/res/values/colors_car.xml
@@ -284,4 +284,8 @@
<color name="car_red_500a">#ffd50000</color>
<color name="car_red_a700">#ffd50000</color>
+
+ <color name="car_keyboard_divider_line">#38ffffff</color>
+ <color name="car_keyboard_text_primary_color">@color/car_grey_50</color>
+ <color name="car_keyboard_text_secondary_color">#8af8f9fa</color>
</resources>
diff --git a/core/res/res/values/colors_device_defaults.xml b/core/res/res/values/colors_device_defaults.xml
index 0fe80a154f7a..ded916fbe7a3 100644
--- a/core/res/res/values/colors_device_defaults.xml
+++ b/core/res/res/values/colors_device_defaults.xml
@@ -42,4 +42,7 @@
<!-- Error color -->
<color name="error_color_device_default_dark">@color/error_color_material_dark</color>
<color name="error_color_device_default_light">@color/error_color_material_light</color>
+
+ <color name="list_divider_color_light">#64000000</color>
+ <color name="list_divider_color_dark">#85ffffff</color>
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 26f3370f0dc5..829d6f57f896 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -55,6 +55,8 @@
<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>
@@ -87,6 +89,8 @@
<string translatable="false" name="status_bar_mobile">mobile</string>
<string translatable="false" name="status_bar_vpn">vpn</string>
<string translatable="false" name="status_bar_ethernet">ethernet</string>
+ <string translatable="false" name="status_bar_microphone">microphone</string>
+ <string translatable="false" name="status_bar_camera">camera</string>
<string translatable="false" name="status_bar_airplane">airplane</string>
<!-- Flag indicating whether the surface flinger has limited
diff --git a/core/res/res/values/dimens_car.xml b/core/res/res/values/dimens_car.xml
index c1ca33e430cd..5014a29f4eab 100644
--- a/core/res/res/values/dimens_car.xml
+++ b/core/res/res/values/dimens_car.xml
@@ -34,7 +34,6 @@
<!-- The diff between keyline 1 and keyline 3. -->
<dimen name="car_keyline_1_keyline_3_diff">88dp</dimen>
<dimen name="car_dialog_action_bar_height">@dimen/car_card_action_bar_height</dimen>
- <dimen name="car_primary_icon_size">44dp</dimen>
<!-- Text size for car -->
<dimen name="car_title_size">32sp</dimen>
@@ -56,16 +55,19 @@
<!-- Common icon size for car app -->
<dimen name="car_icon_size">56dp</dimen>
+ <dimen name="car_primary_icon_size">44dp</dimen>
+ <dimen name="car_secondary_icon_size">36dp</dimen>
- <dimen name="car_card_header_height">96dp</dimen>
- <dimen name="car_card_action_bar_height">96dp</dimen>
+ <dimen name="car_card_header_height">76dp</dimen>
+ <dimen name="car_card_action_bar_height">76dp</dimen>
<!-- Paddings -->
- <dimen name="car_padding_1">4dp</dimen>
- <dimen name="car_padding_2">10dp</dimen>
- <dimen name="car_padding_3">16dp</dimen>
- <dimen name="car_padding_4">28dp</dimen>
- <dimen name="car_padding_5">32dp</dimen>
+ <dimen name="car_padding_0">4dp</dimen>
+ <dimen name="car_padding_1">8dp</dimen>
+ <dimen name="car_padding_2">16dp</dimen>
+ <dimen name="car_padding_3">28dp</dimen>
+ <dimen name="car_padding_4">32dp</dimen>
+ <dimen name="car_padding_5">64dp</dimen>
<!-- Radius -->
<dimen name="car_radius_1">4dp</dimen>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4eb723eb973d..626206b9b9d9 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2808,6 +2808,8 @@
<java-symbol type="string" name="status_bar_mobile" />
<java-symbol type="string" name="status_bar_ethernet" />
<java-symbol type="string" name="status_bar_vpn" />
+ <java-symbol type="string" name="status_bar_microphone" />
+ <java-symbol type="string" name="status_bar_camera" />
<!-- Locale picker -->
<java-symbol type="id" name="locale_search_menu" />
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 3385527ee6ff..fa009bd60c72 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -1475,6 +1475,8 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="listDivider">@color/list_divider_color_light</item>
</style>
<!-- @hide DeviceDefault theme for a window that should use Settings theme colors
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 8c91c370fcf6..002b6a84f592 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -494,6 +494,7 @@ public class SettingsBackupTest {
Settings.Global.WIFI_IS_UNUSABLE_EVENT_METRICS_ENABLED,
Settings.Global.WIFI_LINK_SPEED_METRICS_ENABLED,
Settings.Global.WIFI_PNO_FREQUENCY_CULLING_ENABLED,
+ Settings.Global.WIFI_PNO_RECENCY_SORTING_ENABLED,
Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
Settings.Global.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS,
Settings.Global.WIFI_NETWORK_SHOW_RSSI,
diff --git a/core/tests/coretests/src/android/view/WindowInsetsTest.java b/core/tests/coretests/src/android/view/WindowInsetsTest.java
new file mode 100644
index 000000000000..1c2df2cfedb1
--- /dev/null
+++ b/core/tests/coretests/src/android/view/WindowInsetsTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static org.junit.Assert.assertTrue;
+
+import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
+public class WindowInsetsTest {
+
+ @Test
+ public void systemWindowInsets_afterConsuming_isConsumed() {
+ assertTrue(new WindowInsets(new Rect(1, 2, 3, 4), null, null, false, false, null)
+ .consumeSystemWindowInsets().isConsumed());
+ }
+
+ @Test
+ public void multiNullConstructor_isConsumed() {
+ assertTrue(new WindowInsets(null, null, null, false, false, null).isConsumed());
+ }
+
+ @Test
+ public void singleNullConstructor_isConsumed() {
+ assertTrue(new WindowInsets((Rect) null).isConsumed());
+ }
+
+}
diff --git a/core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java
index f2efabf5f722..88d162b34144 100644
--- a/core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/ModelFileManagerTest.java
@@ -203,6 +203,28 @@ public class ModelFileManagerTest {
}
@Test
+ public void findBestModel_languageIsMoreImportantThanVersion_bestModelComesFirst() {
+ ModelFileManager.ModelFile matchLocaleModel =
+ new ModelFileManager.ModelFile(
+ new File("/path/b"), 1,
+ Collections.singletonList(Locale.forLanguageTag("ja")), false);
+
+ ModelFileManager.ModelFile languageIndependentModel =
+ new ModelFileManager.ModelFile(
+ new File("/path/a"), 2,
+ Collections.emptyList(), true);
+ when(mModelFileSupplier.get())
+ .thenReturn(
+ Arrays.asList(matchLocaleModel, languageIndependentModel));
+
+ ModelFileManager.ModelFile bestModelFile =
+ mModelFileManager.findBestModelFile(
+ LocaleList.forLanguageTags("ja"));
+
+ assertThat(bestModelFile).isEqualTo(matchLocaleModel);
+ }
+
+ @Test
public void modelFileEquals() {
ModelFileManager.ModelFile modelA =
new ModelFileManager.ModelFile(
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java
index e81f6789185e..7467114a7596 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHelperTest.java
@@ -41,6 +41,7 @@ import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.text.format.DateUtils;
+import android.util.StatsLog;
import junit.framework.TestCase;
@@ -258,6 +259,36 @@ public class BatteryStatsHelperTest extends TestCase {
assertThat(time).isEqualTo(TIME_STATE_FOREGROUND_MS);
}
+ @Test
+ public void testDrainTypesSyncedWithProto() {
+ assertEquals(BatterySipper.DrainType.AMBIENT_DISPLAY.ordinal(),
+ StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__AMBIENT_DISPLAY);
+ // AtomsProto has no "APP"
+ assertEquals(BatterySipper.DrainType.BLUETOOTH.ordinal(),
+ StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__BLUETOOTH);
+ assertEquals(BatterySipper.DrainType.CAMERA.ordinal(),
+ StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__CAMERA);
+ assertEquals(BatterySipper.DrainType.CELL.ordinal(),
+ StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__CELL);
+ assertEquals(BatterySipper.DrainType.FLASHLIGHT.ordinal(),
+ StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__FLASHLIGHT);
+ assertEquals(BatterySipper.DrainType.IDLE.ordinal(),
+ StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__IDLE);
+ assertEquals(BatterySipper.DrainType.MEMORY.ordinal(),
+ StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__MEMORY);
+ assertEquals(BatterySipper.DrainType.OVERCOUNTED.ordinal(),
+ StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__OVERCOUNTED);
+ assertEquals(BatterySipper.DrainType.PHONE.ordinal(),
+ StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__PHONE);
+ assertEquals(BatterySipper.DrainType.SCREEN.ordinal(),
+ StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__SCREEN);
+ assertEquals(BatterySipper.DrainType.UNACCOUNTED.ordinal(),
+ StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__UNACCOUNTED);
+ // AtomsProto has no "USER"
+ assertEquals(BatterySipper.DrainType.WIFI.ordinal(),
+ StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER__DRAIN_TYPE__WIFI);
+ }
+
private BatterySipper createTestSmearBatterySipper(long activityTime, double totalPowerMah,
int uidCode, boolean isUidNull) {
final BatterySipper sipper = mock(BatterySipper.class);
diff --git a/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java b/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java
index 01382aae923e..4e0f2a8fe060 100644
--- a/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java
+++ b/core/tests/packagemanagertests/src/android/content/pm/KernelPackageMappingTests.java
@@ -81,7 +81,7 @@ public class KernelPackageMappingTests {
@Test
public void testSharedInstalledPrimary() throws Exception {
- assertEquals("1001", getContent(getKernelPackageFile("shared:android.uid.phone", "appid")));
+ assertEquals("1001", getContent(getKernelPackageFile("shared-android.uid.phone", "appid")));
}
@Test
@@ -92,7 +92,7 @@ public class KernelPackageMappingTests {
@Test
public void testSharedInstalledAll() throws Exception {
- assertEquals("", getContent(getKernelPackageFile("shared:android.uid.phone",
+ assertEquals("", getContent(getKernelPackageFile("shared-android.uid.phone",
"excluded_userids")));
}
diff --git a/data/etc/Android.mk b/data/etc/Android.mk
index 936ad22d4fc5..d24c140ad19a 100644
--- a/data/etc/Android.mk
+++ b/data/etc/Android.mk
@@ -47,3 +47,11 @@ LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/sysconfig
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
+
+########################
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.timezone.updater.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_RELATIVE_PATH := permissions
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
diff --git a/data/etc/com.android.timezone.updater.xml b/data/etc/com.android.timezone.updater.xml
new file mode 100644
index 000000000000..60a66e22027d
--- /dev/null
+++ b/data/etc/com.android.timezone.updater.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<permissions>
+ <privapp-permissions package="com.android.timezone.updater">
+ <permission name="android.permission.QUERY_TIME_ZONE_RULES" />
+ <permission name="android.permission.UPDATE_TIME_ZONE_RULES" />
+ </privapp-permissions>
+</permissions>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 68f24fb7b661..a4c5ed2ee30f 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -173,6 +173,7 @@
<assign-permission name="android.permission.ACCESS_LOWPAN_STATE" uid="lowpan" />
<assign-permission name="android.permission.MANAGE_LOWPAN_INTERFACES" uid="lowpan" />
+ <assign-permission name="android.permission.BATTERY_STATS" uid="statsd" />
<assign-permission name="android.permission.DUMP" uid="statsd" />
<assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="statsd" />
<assign-permission name="android.permission.STATSCOMPANION" uid="statsd" />
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index c7945bd02c49..84cb5f80ece3 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -194,6 +194,8 @@ applications that come with the platform
<privapp-permissions package="com.android.providers.calendar">
<permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/>
+ <permission name="android.permission.INTERACT_ACROSS_USERS" />
+ <permission name="android.permission.MANAGE_USERS" />
<permission name="android.permission.UPDATE_APP_OPS_STATS"/>
<permission name="android.permission.USE_RESERVED_DISK"/>
</privapp-permissions>
diff --git a/graphics/java/android/graphics/RecordingCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java
index fd5d62406da7..67ad4045868e 100644
--- a/graphics/java/android/graphics/RecordingCanvas.java
+++ b/graphics/java/android/graphics/RecordingCanvas.java
@@ -19,6 +19,7 @@ package android.graphics;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.Pools.SynchronizedPool;
+import android.view.DisplayListCanvas;
import android.view.TextureLayer;
import dalvik.annotation.optimization.CriticalNative;
@@ -34,7 +35,7 @@ import dalvik.annotation.optimization.FastNative;
* {@link RenderNode#endRecording()} is called. It must not be retained beyond that as it is
* internally reused.
*/
-public final class RecordingCanvas extends BaseRecordingCanvas {
+public final class RecordingCanvas extends DisplayListCanvas {
// The recording canvas pool should be large enough to handle a deeply nested
// view hierarchy because display lists are generated recursively.
private static final int POOL_LIMIT = 25;
@@ -89,7 +90,8 @@ public final class RecordingCanvas extends BaseRecordingCanvas {
// Constructors
///////////////////////////////////////////////////////////////////////////
- private RecordingCanvas(@NonNull RenderNode node, int width, int height) {
+ /** @hide */
+ protected RecordingCanvas(@NonNull RenderNode node, int width, int height) {
super(nCreateDisplayListCanvas(node.mNativeRenderNode, width, height));
mDensity = 0; // disable bitmap density scaling
}
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index c10e482f1d33..835b735ad55f 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -38,11 +38,13 @@ import android.security.keymaster.KeymasterBlob;
import android.security.keymaster.KeymasterCertificateChain;
import android.security.keymaster.KeymasterDefs;
import android.security.keymaster.OperationResult;
+import android.security.keystore.IKeystoreService;
import android.security.keystore.KeyExpiredException;
import android.security.keystore.KeyNotYetValidException;
import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProtection;
+import android.security.keystore.KeystoreResponse;
import android.security.keystore.StrongBoxUnavailableException;
import android.security.keystore.UserNotAuthenticatedException;
import android.util.Log;
@@ -52,8 +54,11 @@ import java.math.BigInteger;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
+import java.util.Arrays;
import java.util.List;
import java.util.Locale;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
import sun.security.util.ObjectIdentifier;
import sun.security.x509.AlgorithmId;
@@ -303,6 +308,31 @@ public class KeyStore {
}
}
+ /**
+ * List uids of all keys that are auth bound to the current user.
+ * Only system is allowed to call this method.
+ */
+ @UnsupportedAppUsage
+ public int[] listUidsOfAuthBoundKeys() {
+ final int MAX_RESULT_SIZE = 100;
+ int[] uidsOut = new int[MAX_RESULT_SIZE];
+ try {
+ int rc = mBinder.listUidsOfAuthBoundKeys(uidsOut);
+ if (rc != NO_ERROR) {
+ Log.w(TAG, String.format("listUidsOfAuthBoundKeys failed with error code %d", rc));
+ return null;
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to keystore", e);
+ return null;
+ } catch (android.os.ServiceSpecificException e) {
+ Log.w(TAG, "KeyStore exception", e);
+ return null;
+ }
+ // Remove any 0 entries
+ return Arrays.stream(uidsOut).filter(x -> x > 0).toArray();
+ }
+
public String[] list(String prefix) {
return list(prefix, UID_SELF);
}
@@ -451,27 +481,107 @@ public class KeyStore {
public boolean addRngEntropy(byte[] data, int flags) {
try {
- return mBinder.addRngEntropy(data, flags) == NO_ERROR;
+ KeystoreResultPromise promise = new KeystoreResultPromise();
+ int errorCode = mBinder.addRngEntropy(promise, data, flags);
+ if (errorCode == NO_ERROR) {
+ return promise.getFuture().get().getErrorCode() == NO_ERROR;
+ } else {
+ return false;
+ }
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return false;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "AddRngEntropy completed with exception", e);
+ return false;
}
}
+ private class KeyCharacteristicsCallbackResult {
+ private KeystoreResponse keystoreResponse;
+ private KeyCharacteristics keyCharacteristics;
+
+ public KeyCharacteristicsCallbackResult(KeystoreResponse keystoreResponse,
+ KeyCharacteristics keyCharacteristics) {
+ this.keystoreResponse = keystoreResponse;
+ this.keyCharacteristics = keyCharacteristics;
+ }
+
+ public KeystoreResponse getKeystoreResponse() {
+ return keystoreResponse;
+ }
+
+ public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
+ this.keystoreResponse = keystoreResponse;
+ }
+
+ public KeyCharacteristics getKeyCharacteristics() {
+ return keyCharacteristics;
+ }
+
+ public void setKeyCharacteristics(KeyCharacteristics keyCharacteristics) {
+ this.keyCharacteristics = keyCharacteristics;
+ }
+ }
+
+ private class KeyCharacteristicsPromise
+ extends android.security.keystore.IKeystoreKeyCharacteristicsCallback.Stub {
+ final private CompletableFuture<KeyCharacteristicsCallbackResult> future =
+ new CompletableFuture<KeyCharacteristicsCallbackResult>();
+ @Override
+ public void onFinished(KeystoreResponse keystoreResponse,
+ KeyCharacteristics keyCharacteristics)
+ throws android.os.RemoteException {
+ future.complete(
+ new KeyCharacteristicsCallbackResult(keystoreResponse, keyCharacteristics));
+ }
+ public final CompletableFuture<KeyCharacteristicsCallbackResult> getFuture() {
+ return future;
+ }
+ };
+
+ private int generateKeyInternal(String alias, KeymasterArguments args, byte[] entropy, int uid,
+ int flags, KeyCharacteristics outCharacteristics)
+ throws RemoteException, ExecutionException, InterruptedException {
+ KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+ int error = mBinder.generateKey(promise, alias, args, entropy, uid, flags);
+ if (error != NO_ERROR) {
+ Log.e(TAG, "generateKeyInternal failed on request " + error);
+ return error;
+ }
+
+ KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+ error = result.getKeystoreResponse().getErrorCode();
+ if (error != NO_ERROR) {
+ Log.e(TAG, "generateKeyInternal failed on response " + error);
+ return error;
+ }
+ KeyCharacteristics characteristics = result.getKeyCharacteristics();
+ if (characteristics == null) {
+ Log.e(TAG, "generateKeyInternal got empty key cheractariestics " + error);
+ return SYSTEM_ERROR;
+ }
+ outCharacteristics.shallowCopyFrom(characteristics);
+ return NO_ERROR;
+ }
+
public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
int flags, KeyCharacteristics outCharacteristics) {
try {
entropy = entropy != null ? entropy : new byte[0];
args = args != null ? args : new KeymasterArguments();
- int error = mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
+ int error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
if (error == KEY_ALREADY_EXISTS) {
mBinder.del(alias, uid);
- error = mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
+ error = generateKeyInternal(alias, args, entropy, uid, flags, outCharacteristics);
}
return error;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "generateKey completed with exception", e);
+ return SYSTEM_ERROR;
}
}
@@ -485,10 +595,24 @@ public class KeyStore {
try {
clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
- return mBinder.getKeyCharacteristics(alias, clientId, appId, uid, outCharacteristics);
+ KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+ int error = mBinder.getKeyCharacteristics(promise, alias, clientId, appId, uid);
+ if (error != NO_ERROR) return error;
+
+ KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+ error = result.getKeystoreResponse().getErrorCode();
+ if (error != NO_ERROR) return error;
+
+ KeyCharacteristics characteristics = result.getKeyCharacteristics();
+ if (characteristics == null) return SYSTEM_ERROR;
+ outCharacteristics.shallowCopyFrom(characteristics);
+ return NO_ERROR;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "GetKeyCharacteristics completed with exception", e);
+ return SYSTEM_ERROR;
}
}
@@ -497,20 +621,40 @@ public class KeyStore {
return getKeyCharacteristics(alias, clientId, appId, UID_SELF, outCharacteristics);
}
+ private int importKeyInternal(String alias, KeymasterArguments args, int format, byte[] keyData,
+ int uid, int flags, KeyCharacteristics outCharacteristics)
+ throws RemoteException, ExecutionException, InterruptedException {
+ KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+ int error = mBinder.importKey(promise, alias, args, format, keyData, uid, flags);
+ if (error != NO_ERROR) return error;
+
+ KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+ error = result.getKeystoreResponse().getErrorCode();
+ if (error != NO_ERROR) return error;
+
+ KeyCharacteristics characteristics = result.getKeyCharacteristics();
+ if (characteristics == null) return SYSTEM_ERROR;
+ outCharacteristics.shallowCopyFrom(characteristics);
+ return NO_ERROR;
+ }
+
public int importKey(String alias, KeymasterArguments args, int format, byte[] keyData,
int uid, int flags, KeyCharacteristics outCharacteristics) {
try {
- int error = mBinder.importKey(alias, args, format, keyData, uid, flags,
+ int error = importKeyInternal(alias, args, format, keyData, uid, flags,
outCharacteristics);
if (error == KEY_ALREADY_EXISTS) {
mBinder.del(alias, uid);
- error = mBinder.importKey(alias, args, format, keyData, uid, flags,
+ error = importKeyInternal(alias, args, format, keyData, uid, flags,
outCharacteristics);
}
return error;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "ImportKey completed with exception", e);
+ return SYSTEM_ERROR;
}
}
@@ -578,34 +722,79 @@ public class KeyStore {
return true;
}
+ private int importWrappedKeyInternal(String wrappedKeyAlias, byte[] wrappedKey,
+ String wrappingKeyAlias,
+ byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid,
+ KeyCharacteristics outCharacteristics)
+ throws RemoteException, ExecutionException, InterruptedException {
+ KeyCharacteristicsPromise promise = new KeyCharacteristicsPromise();
+ int error = mBinder.importWrappedKey(promise, wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+ maskingKey, args, rootSid, fingerprintSid);
+ if (error != NO_ERROR) return error;
+
+ KeyCharacteristicsCallbackResult result = promise.getFuture().get();
+ error = result.getKeystoreResponse().getErrorCode();
+ if (error != NO_ERROR) return error;
+
+ KeyCharacteristics characteristics = result.getKeyCharacteristics();
+ if (characteristics == null) return SYSTEM_ERROR;
+ outCharacteristics.shallowCopyFrom(characteristics);
+ return NO_ERROR;
+ }
+
public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey,
String wrappingKeyAlias,
byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid,
KeyCharacteristics outCharacteristics) {
+ // TODO b/119217337 uid parameter gets silently ignored.
try {
- int error = mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+ int error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
if (error == KEY_ALREADY_EXISTS) {
- mBinder.del(wrappedKeyAlias, -1);
- error = mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+ mBinder.del(wrappedKeyAlias, UID_SELF);
+ error = importWrappedKeyInternal(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
}
return error;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "ImportWrappedKey completed with exception", e);
+ return SYSTEM_ERROR;
}
}
+ private class ExportKeyPromise
+ extends android.security.keystore.IKeystoreExportKeyCallback.Stub {
+ final private CompletableFuture<ExportResult> future = new CompletableFuture<ExportResult>();
+ @Override
+ public void onFinished(ExportResult exportKeyResult) throws android.os.RemoteException {
+ future.complete(exportKeyResult);
+ }
+ public final CompletableFuture<ExportResult> getFuture() {
+ return future;
+ }
+ };
+
public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
KeymasterBlob appId, int uid) {
try {
clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
- return mBinder.exportKey(alias, format, clientId, appId, uid);
+ ExportKeyPromise promise = new ExportKeyPromise();
+ int error = mBinder.exportKey(promise, alias, format, clientId, appId, uid);
+ if (error == NO_ERROR) {
+ return promise.getFuture().get();
+ } else {
+ return new ExportResult(error);
+ }
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "ExportKey completed with exception", e);
+ return null;
}
}
public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
@@ -613,15 +802,37 @@ public class KeyStore {
return exportKey(alias, format, clientId, appId, UID_SELF);
}
+ private class OperationPromise
+ extends android.security.keystore.IKeystoreOperationResultCallback.Stub {
+ final private CompletableFuture<OperationResult> future = new CompletableFuture<OperationResult>();
+ @Override
+ public void onFinished(OperationResult operationResult) throws android.os.RemoteException {
+ future.complete(operationResult);
+ }
+ public final CompletableFuture<OperationResult> getFuture() {
+ return future;
+ }
+ };
+
public OperationResult begin(String alias, int purpose, boolean pruneable,
KeymasterArguments args, byte[] entropy, int uid) {
try {
args = args != null ? args : new KeymasterArguments();
entropy = entropy != null ? entropy : new byte[0];
- return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
+ OperationPromise promise = new OperationPromise();
+ int errorCode = mBinder.begin(promise, getToken(), alias, purpose, pruneable, args,
+ entropy, uid);
+ if (errorCode == NO_ERROR) {
+ return promise.getFuture().get();
+ } else {
+ return new OperationResult(errorCode);
+ }
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "Begin completed with exception", e);
+ return null;
}
}
@@ -636,10 +847,19 @@ public class KeyStore {
try {
arguments = arguments != null ? arguments : new KeymasterArguments();
input = input != null ? input : new byte[0];
- return mBinder.update(token, arguments, input);
+ OperationPromise promise = new OperationPromise();
+ int errorCode = mBinder.update(promise, token, arguments, input);
+ if (errorCode == NO_ERROR) {
+ return promise.getFuture().get();
+ } else {
+ return new OperationResult(errorCode);
+ }
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "Update completed with exception", e);
+ return null;
}
}
@@ -649,10 +869,19 @@ public class KeyStore {
arguments = arguments != null ? arguments : new KeymasterArguments();
entropy = entropy != null ? entropy : new byte[0];
signature = signature != null ? signature : new byte[0];
- return mBinder.finish(token, arguments, signature, entropy);
+ OperationPromise promise = new OperationPromise();
+ int errorCode = mBinder.finish(promise, token, arguments, signature, entropy);
+ if (errorCode == NO_ERROR) {
+ return promise.getFuture().get();
+ } else {
+ return new OperationResult(errorCode);
+ }
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "Finish completed with exception", e);
+ return null;
}
}
@@ -660,12 +889,33 @@ public class KeyStore {
return finish(token, arguments, signature, null);
}
+ private class KeystoreResultPromise
+ extends android.security.keystore.IKeystoreResponseCallback.Stub {
+ final private CompletableFuture<KeystoreResponse> future = new CompletableFuture<KeystoreResponse>();
+ @Override
+ public void onFinished(KeystoreResponse keystoreResponse) throws android.os.RemoteException {
+ future.complete(keystoreResponse);
+ }
+ public final CompletableFuture<KeystoreResponse> getFuture() {
+ return future;
+ }
+ };
+
public int abort(IBinder token) {
try {
- return mBinder.abort(token);
+ KeystoreResultPromise promise = new KeystoreResultPromise();
+ int errorCode = mBinder.abort(promise, token);
+ if (errorCode == NO_ERROR) {
+ return promise.getFuture().get().getErrorCode();
+ } else {
+ return errorCode;
+ }
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "Abort completed with exception", e);
+ return SYSTEM_ERROR;
}
}
@@ -747,6 +997,47 @@ public class KeyStore {
return onUserPasswordChanged(UserHandle.getUserId(Process.myUid()), newPassword);
}
+ private class KeyAttestationCallbackResult {
+ private KeystoreResponse keystoreResponse;
+ private KeymasterCertificateChain certificateChain;
+
+ public KeyAttestationCallbackResult(KeystoreResponse keystoreResponse,
+ KeymasterCertificateChain certificateChain) {
+ this.keystoreResponse = keystoreResponse;
+ this.certificateChain = certificateChain;
+ }
+
+ public KeystoreResponse getKeystoreResponse() {
+ return keystoreResponse;
+ }
+
+ public void setKeystoreResponse(KeystoreResponse keystoreResponse) {
+ this.keystoreResponse = keystoreResponse;
+ }
+
+ public KeymasterCertificateChain getCertificateChain() {
+ return certificateChain;
+ }
+
+ public void setCertificateChain(KeymasterCertificateChain certificateChain) {
+ this.certificateChain = certificateChain;
+ }
+ }
+
+ private class CertificateChainPromise
+ extends android.security.keystore.IKeystoreCertificateChainCallback.Stub {
+ final private CompletableFuture<KeyAttestationCallbackResult> future = new CompletableFuture<KeyAttestationCallbackResult>();
+ @Override
+ public void onFinished(KeystoreResponse keystoreResponse,
+ KeymasterCertificateChain certificateChain) throws android.os.RemoteException {
+ future.complete(new KeyAttestationCallbackResult(keystoreResponse, certificateChain));
+ }
+ public final CompletableFuture<KeyAttestationCallbackResult> getFuture() {
+ return future;
+ }
+ };
+
+
public int attestKey(
String alias, KeymasterArguments params, KeymasterCertificateChain outChain) {
try {
@@ -756,10 +1047,21 @@ public class KeyStore {
if (outChain == null) {
outChain = new KeymasterCertificateChain();
}
- return mBinder.attestKey(alias, params, outChain);
+ CertificateChainPromise promise = new CertificateChainPromise();
+ int error = mBinder.attestKey(promise, alias, params);
+ if (error != NO_ERROR) return error;
+ KeyAttestationCallbackResult result = promise.getFuture().get();
+ error = result.getKeystoreResponse().getErrorCode();
+ if (error == NO_ERROR) {
+ outChain.shallowCopyFrom(result.getCertificateChain());
+ }
+ return error;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "AttestKey completed with exception", e);
+ return SYSTEM_ERROR;
}
}
@@ -771,10 +1073,21 @@ public class KeyStore {
if (outChain == null) {
outChain = new KeymasterCertificateChain();
}
- return mBinder.attestDeviceIds(params, outChain);
+ CertificateChainPromise promise = new CertificateChainPromise();
+ int error = mBinder.attestDeviceIds(promise, params);
+ if (error != NO_ERROR) return error;
+ KeyAttestationCallbackResult result = promise.getFuture().get();
+ error = result.getKeystoreResponse().getErrorCode();
+ if (error == NO_ERROR) {
+ outChain.shallowCopyFrom(result.getCertificateChain());
+ }
+ return error;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return SYSTEM_ERROR;
+ } catch (ExecutionException | InterruptedException e) {
+ Log.e(TAG, "AttestDevicdeIds completed with exception", e);
+ return SYSTEM_ERROR;
}
}
diff --git a/keystore/java/android/security/keystore/KeystoreResponse.java b/keystore/java/android/security/keystore/KeystoreResponse.java
new file mode 100644
index 000000000000..3a229cb610a8
--- /dev/null
+++ b/keystore/java/android/security/keystore/KeystoreResponse.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.keystore;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelFormatException;
+
+/**
+ * The Java side of the KeystoreResponse.
+ * <p>
+ * Serialization code for this and subclasses must be kept in sync with system/security/keystore.
+ * @hide
+ */
+public class KeystoreResponse implements Parcelable {
+ public final int error_code_;
+ public final String error_msg_;
+
+ public static final Parcelable.Creator<KeystoreResponse> CREATOR = new
+ Parcelable.Creator<KeystoreResponse>() {
+ @Override
+ public KeystoreResponse createFromParcel(Parcel in) {
+ final int error_code = in.readInt();
+ final String error_msg = in.readString();
+ return new KeystoreResponse(error_code, error_msg);
+ }
+
+ @Override
+ public KeystoreResponse[] newArray(int size) {
+ return new KeystoreResponse[size];
+ }
+ };
+
+ protected KeystoreResponse(int error_code, String error_msg) {
+ this.error_code_ = error_code;
+ this.error_msg_ = error_msg;
+ }
+
+ /**
+ * @return the error_code_
+ */
+ public final int getErrorCode() {
+ return error_code_;
+ }
+
+ /**
+ * @return the error_msg_
+ */
+ public final String getErrorMessage() {
+ return error_msg_;
+ }
+
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(error_code_);
+ out.writeString(error_msg_);
+ }
+}
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 843c1461e21b..1cb0d25d8c08 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -72,7 +72,7 @@ static volatile int32_t gCount = 0;
const char* AssetManager::RESOURCES_FILENAME = "resources.arsc";
const char* AssetManager::IDMAP_BIN = "/system/bin/idmap";
-const char* AssetManager::OVERLAY_DIR = "/vendor/overlay";
+const char* AssetManager::VENDOR_OVERLAY_DIR = "/vendor/overlay";
const char* AssetManager::PRODUCT_OVERLAY_DIR = "/product/overlay";
const char* AssetManager::PRODUCT_SERVICES_OVERLAY_DIR = "/product_services/overlay";
const char* AssetManager::OVERLAY_THEME_DIR_PROPERTY = "ro.boot.vendor.overlay.theme";
diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h
index cdb87bcb8e11..e22e2d239a55 100644
--- a/libs/androidfw/include/androidfw/AssetManager.h
+++ b/libs/androidfw/include/androidfw/AssetManager.h
@@ -59,13 +59,13 @@ class AssetManager : public AAssetManager {
public:
static const char* RESOURCES_FILENAME;
static const char* IDMAP_BIN;
- static const char* OVERLAY_DIR;
+ static const char* VENDOR_OVERLAY_DIR;
static const char* PRODUCT_OVERLAY_DIR;
static const char* PRODUCT_SERVICES_OVERLAY_DIR;
/*
* If OVERLAY_THEME_DIR_PROPERTY is set, search for runtime resource overlay
- * APKs in OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to
- * OVERLAY_DIR.
+ * APKs in VENDOR_OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in
+ * addition to VENDOR_OVERLAY_DIR.
*/
static const char* OVERLAY_THEME_DIR_PROPERTY;
static const char* TARGET_PACKAGE_NAME;
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index d401b385075e..6ae59990d0ab 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -164,7 +164,11 @@ bool SkiaOpenGLPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior,
if (surface) {
mRenderThread.requireGlContext();
- mEglSurface = mEglManager.createSurface(surface, colorMode);
+ auto newSurface = mEglManager.createSurface(surface, colorMode);
+ if (!newSurface) {
+ return false;
+ }
+ mEglSurface = newSurface.unwrap();
}
if (colorMode == ColorMode::SRGB) {
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index d4ffddde8def..65ced6ad9316 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -261,7 +261,7 @@ void EglManager::createPBufferSurface() {
}
}
-EGLSurface EglManager::createSurface(EGLNativeWindowType window, ColorMode colorMode) {
+Result<EGLSurface, EGLint> EglManager::createSurface(EGLNativeWindowType window, ColorMode colorMode) {
LOG_ALWAYS_FATAL_IF(!hasEglContext(), "Not initialized");
bool wideColorGamut = colorMode == ColorMode::WideColorGamut && EglExtensions.glColorSpace &&
@@ -311,9 +311,9 @@ EGLSurface EglManager::createSurface(EGLNativeWindowType window, ColorMode color
EGLSurface surface = eglCreateWindowSurface(
mEglDisplay, wideColorGamut ? mEglConfigWideGamut : mEglConfig, window, attribs);
- LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
- "Failed to create EGLSurface for window %p, eglErr = %s", (void*)window,
- eglErrorString());
+ if (surface == EGL_NO_SURFACE) {
+ return Error<EGLint> { eglGetError() };
+ }
if (mSwapBehavior != SwapBehavior::Preserved) {
LOG_ALWAYS_FATAL_IF(eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR,
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 55c81d42d8a0..2a44f7e10b80 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -25,6 +25,7 @@
#include <ui/GraphicBuffer.h>
#include <utils/StrongPointer.h>
#include "IRenderPipeline.h"
+#include "utils/Result.h"
namespace android {
namespace uirenderer {
@@ -47,7 +48,7 @@ public:
bool hasEglContext();
- EGLSurface createSurface(EGLNativeWindowType window, ColorMode colorMode);
+ Result<EGLSurface, EGLint> createSurface(EGLNativeWindowType window, ColorMode colorMode);
void destroySurface(EGLSurface surface);
void destroy();
diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp
index 079520836bb5..a6073ebb5c74 100644
--- a/libs/hwui/tests/unit/RenderNodeTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeTests.cpp
@@ -321,7 +321,7 @@ RENDERTHREAD_TEST(RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) {
// Check that the VD is in the dislay list, and the layer update queue contains the correct
// damage rect.
EXPECT_TRUE(rootNode->getDisplayList()->hasVectorDrawables());
- EXPECT_FALSE(info.layerUpdateQueue->entries().empty());
+ ASSERT_FALSE(info.layerUpdateQueue->entries().empty());
EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode.get());
EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage);
canvasContext->destroy();
diff --git a/libs/hwui/utils/Result.h b/libs/hwui/utils/Result.h
new file mode 100644
index 000000000000..7f33f2e3424d
--- /dev/null
+++ b/libs/hwui/utils/Result.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <variant>
+#include <log/log.h>
+
+namespace android::uirenderer {
+
+template <typename E>
+struct Error {
+ E error;
+};
+
+template <typename R, typename E>
+class Result {
+public:
+ Result(const R& r) : result(std::forward<R>(r)) {}
+ Result(R&& r) : result(std::forward<R>(r)) {}
+ Result(Error<E>&& error) : result(std::forward<Error<E>>(error)) {}
+
+ operator bool() const {
+ return result.index() == 0;
+ }
+
+ R unwrap() const {
+ LOG_ALWAYS_FATAL_IF(result.index() == 1, "unwrap called on error value!");
+ return std::get<R>(result);
+ }
+
+ E error() const {
+ LOG_ALWAYS_FATAL_IF(result.index() == 0, "No error to get from Result");
+ return std::get<Error<E>>(result).error;
+ }
+
+private:
+ std::variant<R, Error<E>> result;
+};
+
+}; // namespace android::uirenderer
diff --git a/libs/services/src/os/StatsLogEventWrapper.cpp b/libs/services/src/os/StatsLogEventWrapper.cpp
index a1a6d9fe0e22..04c4629b5432 100644
--- a/libs/services/src/os/StatsLogEventWrapper.cpp
+++ b/libs/services/src/os/StatsLogEventWrapper.cpp
@@ -85,9 +85,6 @@ status_t StatsLogEventWrapper::readFromParcel(const Parcel* in) {
case StatsLogValue::FLOAT:
mElements.push_back(StatsLogValue(in->readFloat()));
break;
- case StatsLogValue::DOUBLE:
- mElements.push_back(StatsLogValue(in->readDouble()));
- break;
case StatsLogValue::STORAGE:
mElements.push_back(StatsLogValue());
mElements.back().setType(StatsLogValue::STORAGE);
diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
index 8a02a82194df..057a4ae879f4 100644
--- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
@@ -20,9 +20,12 @@ import android.os.SystemClock;
import android.os.connectivity.GpsBatteryStats;
import android.os.SystemProperties;
+import android.server.location.ServerLocationProtoEnums;
+
import android.text.format.DateUtils;
import android.util.Base64;
import android.util.Log;
+import android.util.StatsLog;
import android.util.TimeUtils;
import java.util.Arrays;
@@ -39,11 +42,17 @@ public class GnssMetrics {
private static final String TAG = GnssMetrics.class.getSimpleName();
+ /* Constant which indicates GPS signal quality is as yet unknown */
+ public static final int GPS_SIGNAL_QUALITY_UNKNOWN =
+ ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_UNKNOWN; // -1
+
/* Constant which indicates GPS signal quality is poor */
- public static final int GPS_SIGNAL_QUALITY_POOR = 0;
+ public static final int GPS_SIGNAL_QUALITY_POOR =
+ ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_POOR; // 0
/* Constant which indicates GPS signal quality is good */
- public static final int GPS_SIGNAL_QUALITY_GOOD = 1;
+ public static final int GPS_SIGNAL_QUALITY_GOOD =
+ ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_GOOD; // 1
/* Number of GPS signal quality levels */
public static final int NUM_GPS_SIGNAL_QUALITY_LEVELS = GPS_SIGNAL_QUALITY_GOOD + 1;
@@ -329,11 +338,15 @@ public class GnssMetrics {
/* Last reported Top Four Average CN0 */
private double mLastAverageCn0;
+ /* Last reported signal quality bin (based on Top Four Average CN0) */
+ private int mLastSignalLevel;
+
public GnssPowerMetrics(IBatteryStats stats) {
mBatteryStats = stats;
// Used to initialize the variable to a very small value (unachievable in practice) so that
// the first CNO report will trigger an update to BatteryStats
mLastAverageCn0 = -100.0;
+ mLastSignalLevel = GPS_SIGNAL_QUALITY_UNKNOWN;
}
/**
@@ -384,8 +397,13 @@ public class GnssMetrics {
if (Math.abs(avgCn0 - mLastAverageCn0) < REPORTING_THRESHOLD_DB_HZ) {
return;
}
+ int signalLevel = getSignalLevel(avgCn0);
+ if (signalLevel != mLastSignalLevel) {
+ StatsLog.write(StatsLog.GPS_SIGNAL_QUALITY_CHANGED, signalLevel);
+ mLastSignalLevel = signalLevel;
+ }
try {
- mBatteryStats.noteGpsSignalQuality(getSignalLevel(avgCn0));
+ mBatteryStats.noteGpsSignalQuality(signalLevel);
mLastAverageCn0 = avgCn0;
} catch (Exception e) {
Log.w(TAG, "Exception", e);
diff --git a/media/java/android/media/AudioPresentation.java b/media/java/android/media/AudioPresentation.java
index 1cc650bf2702..823af656abaa 100644
--- a/media/java/android/media/AudioPresentation.java
+++ b/media/java/android/media/AudioPresentation.java
@@ -18,7 +18,6 @@ package android.media;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.TestApi;
import android.icu.util.ULocale;
import java.lang.annotation.Retention;
@@ -172,6 +171,10 @@ public final class AudioPresentation {
return localeLabels;
}
+ private Map<ULocale, String> getULabels() {
+ return mLabels;
+ }
+
/**
* @return the locale corresponding to audio presentation's ISO 639-1/639-2 language code.
*/
@@ -231,17 +234,24 @@ public final class AudioPresentation {
AudioPresentation obj = (AudioPresentation) o;
return mPresentationId == obj.getPresentationId()
&& mProgramId == obj.getProgramId()
- && mLanguage == obj.getULocale()
+ && mLanguage.equals(obj.getULocale())
&& mMasteringIndication == obj.getMasteringIndication()
&& mAudioDescriptionAvailable == obj.hasAudioDescription()
&& mSpokenSubtitlesAvailable == obj.hasSpokenSubtitles()
&& mDialogueEnhancementAvailable == obj.hasDialogueEnhancement()
- && mLabels.equals(obj.getLabels());
+ && mLabels.equals(obj.getULabels());
}
@Override
public int hashCode() {
- return Objects.hashCode(mPresentationId);
+ return Objects.hash(mPresentationId,
+ mProgramId,
+ mLanguage.hashCode(),
+ mMasteringIndication,
+ mAudioDescriptionAvailable,
+ mSpokenSubtitlesAvailable,
+ mDialogueEnhancementAvailable,
+ mLabels.hashCode());
}
/**
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 24b7f36e228b..cdbc7b44f905 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -418,9 +418,6 @@ public final class MediaDrm implements AutoCloseable {
/**
* Returns the status code for the key
- * @return one of {@link #STATUS_USABLE}, {@link #STATUS_EXPIRED},
- * {@link #STATUS_OUTPUT_NOT_ALLOWED}, {@link #STATUS_PENDING}
- * or {@link #STATUS_INTERNAL_ERROR}.
*/
@KeyStatusCode
public int getStatusCode() { return mStatusCode; }
@@ -654,13 +651,7 @@ public final class MediaDrm implements AutoCloseable {
* can be queried using {@link #getSecurityLevel}. A session
* ID is returned.
*
- * @param level the new security level, one of
- * {@link #SECURITY_LEVEL_SW_SECURE_CRYPTO},
- * {@link #SECURITY_LEVEL_SW_SECURE_DECODE},
- * {@link #SECURITY_LEVEL_HW_SECURE_CRYPTO},
- * {@link #SECURITY_LEVEL_HW_SECURE_DECODE} or
- * {@link #SECURITY_LEVEL_HW_SECURE_ALL}.
- *
+ * @param level the new security level
* @throws NotProvisionedException if provisioning is needed
* @throws ResourceBusyException if required resources are in use
* @throws IllegalArgumentException if the requested security level is
@@ -790,9 +781,6 @@ public final class MediaDrm implements AutoCloseable {
/**
* Get the type of the request
- * @return one of {@link #REQUEST_TYPE_INITIAL},
- * {@link #REQUEST_TYPE_RENEWAL}, {@link #REQUEST_TYPE_RELEASE},
- * {@link #REQUEST_TYPE_NONE} or {@link #REQUEST_TYPE_UPDATE}
*/
@RequestType
public int getRequestType() { return mRequestType; }
@@ -1051,8 +1039,7 @@ public final class MediaDrm implements AutoCloseable {
* an inactive offline license are not usable for decryption.
*
* @param keySetId selects the offline license
- * @return the offline license state, one of {@link #OFFLINE_LICENSE_USABLE},
- * {@link #OFFLINE_LICENSE_INACTIVE} or {@link #OFFLINE_LICENSE_STATE_UNKNOWN}.
+ * @return the offline license state
* @throws IllegalArgumentException if the keySetId does not refer to an
* offline license.
*/
@@ -1191,9 +1178,7 @@ public final class MediaDrm implements AutoCloseable {
* enforcing compliance with HDCP requirements. Trusted enforcement of
* HDCP policies must be handled by the DRM system.
* <p>
- * @return one of {@link #HDCP_LEVEL_UNKNOWN}, {@link #HDCP_NONE},
- * {@link #HDCP_V1}, {@link #HDCP_V2}, {@link #HDCP_V2_1}, {@link #HDCP_V2_2}
- * or {@link #HDCP_NO_DIGITAL_OUTPUT}.
+ * @return the connected HDCP level
*/
@HdcpLevel
public native int getConnectedHdcpLevel();
@@ -1204,9 +1189,7 @@ public final class MediaDrm implements AutoCloseable {
* that may be connected. If multiple HDCP-capable interfaces are present,
* it indicates the highest of the maximum HDCP levels of all interfaces.
* <p>
- * @return one of {@link #HDCP_LEVEL_UNKNOWN}, {@link #HDCP_NONE},
- * {@link #HDCP_V1}, {@link #HDCP_V2}, {@link #HDCP_V2_1}, {@link #HDCP_V2_2}
- * or {@link #HDCP_NO_DIGITAL_OUTPUT}.
+ * @return the maximum supported HDCP level
*/
@HdcpLevel
public native int getMaxHdcpLevel();
@@ -1296,10 +1279,7 @@ public final class MediaDrm implements AutoCloseable {
* time a session is opened using {@link #openSession}.
* @param sessionId the session to query.
* <p>
- * @return one of {@link #SECURITY_LEVEL_UNKNOWN},
- * {@link #SECURITY_LEVEL_SW_SECURE_CRYPTO}, {@link #SECURITY_LEVEL_SW_SECURE_DECODE},
- * {@link #SECURITY_LEVEL_HW_SECURE_CRYPTO}, {@link #SECURITY_LEVEL_HW_SECURE_DECODE} or
- * {@link #SECURITY_LEVEL_HW_SECURE_ALL}.
+ * @return the security level of the session
*/
@SecurityLevel
public native int getSecurityLevel(@NonNull byte[] sessionId);
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 4919eeb4dacb..c203fa9ca71b 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -272,10 +272,12 @@ final public class MediaExtractor {
public static final class CasInfo {
private final int mSystemId;
private final MediaCas.Session mSession;
+ private final byte[] mPrivateData;
- CasInfo(int systemId, @Nullable MediaCas.Session session) {
+ CasInfo(int systemId, @Nullable MediaCas.Session session, @Nullable byte[] privateData) {
mSystemId = systemId;
mSession = session;
+ mPrivateData = privateData;
}
/**
@@ -288,10 +290,30 @@ final public class MediaExtractor {
}
/**
+ * Retrieves the private data in the CA_Descriptor associated with a track.
+ * Some CAS systems may need this to initialize the CAS plugin object. This
+ * private data can only be retrieved before a valid {@link MediaCas} object
+ * is set on the extractor.
+ * <p>
+ * @see MediaExtractor#setMediaCas
+ * <p>
+ * @return a byte array containing the private data. A null return value
+ * indicates that the private data is unavailable. An empty array,
+ * on the other hand, indicates that the private data is empty
+ * (zero in length).
+ */
+ @Nullable
+ public byte[] getPrivateData() {
+ return mPrivateData;
+ }
+
+ /**
* Retrieves the {@link MediaCas.Session} associated with a track. The
* session is needed to initialize a descrambler in order to decode the
- * scrambled track.
+ * scrambled track. The session object can only be retrieved after a valid
+ * {@link MediaCas} object is set on the extractor.
* <p>
+ * @see MediaExtractor#setMediaCas
* @see MediaDescrambler#setMediaCasSession
* <p>
* @return a {@link MediaCas.Session} object associated with a track.
@@ -321,6 +343,13 @@ final public class MediaExtractor {
if (formatMap.containsKey(MediaFormat.KEY_CA_SYSTEM_ID)) {
int systemId = ((Integer)formatMap.get(MediaFormat.KEY_CA_SYSTEM_ID)).intValue();
MediaCas.Session session = null;
+ byte[] privateData = null;
+ if (formatMap.containsKey(MediaFormat.KEY_CA_PRIVATE_DATA)) {
+ ByteBuffer buf = (ByteBuffer) formatMap.get(MediaFormat.KEY_CA_PRIVATE_DATA);
+ buf.rewind();
+ privateData = new byte[buf.remaining()];
+ buf.get(privateData);
+ }
if (mMediaCas != null && formatMap.containsKey(MediaFormat.KEY_CA_SESSION_ID)) {
ByteBuffer buf = (ByteBuffer) formatMap.get(MediaFormat.KEY_CA_SESSION_ID);
buf.rewind();
@@ -328,7 +357,7 @@ final public class MediaExtractor {
buf.get(sessionId);
session = mMediaCas.createFromSessionId(toByteArray(sessionId));
}
- return new CasInfo(systemId, session);
+ return new CasInfo(systemId, session, privateData);
}
return null;
}
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index d10cbbc295c7..5dee16e03542 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -919,7 +919,7 @@ public final class MediaFormat {
* a media track.
* <p>
* This key is set by {@link MediaExtractor} if the track is scrambled with a conditional
- * access system.
+ * access system, regardless of the presence of a valid {@link MediaCas} object.
* <p>
* The associated value is an integer.
* @hide
@@ -930,13 +930,25 @@ public final class MediaFormat {
* A key describing the {@link MediaCas.Session} object associated with a media track.
* <p>
* This key is set by {@link MediaExtractor} if the track is scrambled with a conditional
- * access system.
+ * access system, after it receives a valid {@link MediaCas} object.
* <p>
* The associated value is a ByteBuffer.
* @hide
*/
public static final String KEY_CA_SESSION_ID = "ca-session-id";
+
+ /**
+ * A key describing the private data in the CA_descriptor associated with a media track.
+ * <p>
+ * This key is set by {@link MediaExtractor} if the track is scrambled with a conditional
+ * access system, before it receives a valid {@link MediaCas} object.
+ * <p>
+ * The associated value is a ByteBuffer.
+ * @hide
+ */
+ public static final String KEY_CA_PRIVATE_DATA = "ca-private-data";
+
/* package private */ MediaFormat(Map<String, Object> map) {
mMap = map;
}
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index 4e901629b114..e8b2f6513984 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -856,11 +856,9 @@ public abstract class MediaPlayer2 implements AutoCloseable
* Checks whether the MediaPlayer2 is looping or non-looping.
*
* @return true if the MediaPlayer2 is currently looping, false otherwise
- * @hide
*/
- public boolean isLooping() {
- return false;
- }
+ // This is a synchronous call.
+ public abstract boolean isLooping();
/**
* Sets the audio session ID.
@@ -875,7 +873,8 @@ public abstract class MediaPlayer2 implements AutoCloseable
* When created, a MediaPlayer2 instance automatically generates its own audio session ID.
* However, it is possible to force this player to be part of an already existing audio session
* by calling this method.
- * This method must be called before one of the overloaded <code> setDataSource </code> methods.
+ * This method must be called when player is in {@link #PLAYER_STATE_IDLE} or
+ * {@link #PLAYER_STATE_PREPARED} state in order to have sessionId take effect.
* @return a token which can be used to cancel the operation later with {@link #cancelCommand}.
*/
// This is an asynchronous call.
@@ -885,8 +884,10 @@ public abstract class MediaPlayer2 implements AutoCloseable
* Returns the audio session ID.
*
* @return the audio session ID. {@see #setAudioSessionId(int)}
- * Note that the audio session ID is 0 only if a problem occured when the MediaPlayer2 was contructed.
+ * Note that the audio session ID is 0 only if a problem occured when the MediaPlayer2 was
+ * contructed.
*/
+ // This is a synchronous call.
public abstract int getAudioSessionId();
/**
@@ -907,7 +908,6 @@ public abstract class MediaPlayer2 implements AutoCloseable
// This is an asynchronous call.
public abstract Object attachAuxEffect(int effectId);
-
/**
* Sets the send level of the player to the attached auxiliary effect.
* See {@link #attachAuxEffect(int)}. The level value range is 0 to 1.0.
@@ -972,36 +972,10 @@ public abstract class MediaPlayer2 implements AutoCloseable
* @return List of track info. The total number of tracks is the array length.
* Must be called again if an external timed text source has been added after
* addTimedTextSource method is called.
+ * @throws IllegalStateException if it is called in an invalid state.
*/
public abstract List<TrackInfo> getTrackInfo();
- /* Do not change these values without updating their counterparts
- * in include/media/stagefright/MediaDefs.h and media/libstagefright/MediaDefs.cpp!
- */
- /**
- * MIME type for SubRip (SRT) container. Used in addTimedTextSource APIs.
- * @hide
- */
- public static final String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
-
- /**
- * MIME type for WebVTT subtitle data.
- * @hide
- */
- public static final String MEDIA_MIMETYPE_TEXT_VTT = "text/vtt";
-
- /**
- * MIME type for CEA-608 closed caption data.
- * @hide
- */
- public static final String MEDIA_MIMETYPE_TEXT_CEA_608 = "text/cea-608";
-
- /**
- * MIME type for CEA-708 closed caption data.
- * @hide
- */
- public static final String MEDIA_MIMETYPE_TEXT_CEA_708 = "text/cea-708";
-
/**
* Returns the index of the audio, video, or subtitle track currently selected for playback,
* The return value is an index into the array returned by {@link #getTrackInfo()}, and can
@@ -1202,7 +1176,7 @@ public abstract class MediaPlayer2 implements AutoCloseable
public abstract void unregisterEventCallback(EventCallback eventCallback);
/* Do not change these values without updating their counterparts
- * in include/media/mediaplayer2.h!
+ * in include/media/MediaPlayer2Types.h!
*/
/** Unspecified media player error.
* @see EventCallback#onError
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 4ac0188581e8..babf24ee08c8 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -56,7 +56,6 @@ import java.net.URL;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
@@ -64,7 +63,6 @@ import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.UUID;
-import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
@@ -700,7 +698,8 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
// return true if there is a next data source, false otherwise.
// This function should be always called on |mHandlerThread|.
private boolean prepareNextDataSource() {
- if (Looper.myLooper() != mHandlerThread.getLooper()) {
+ HandlerThread handlerThread = mHandlerThread;
+ if (handlerThread != null && Looper.myLooper() != handlerThread.getLooper()) {
Log.e(TAG, "prepareNextDataSource: called on wrong looper");
}
@@ -736,7 +735,8 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
// This function should be always called on |mHandlerThread|.
private void playNextDataSource() {
- if (Looper.myLooper() != mHandlerThread.getLooper()) {
+ HandlerThread handlerThread = mHandlerThread;
+ if (handlerThread != null && Looper.myLooper() != handlerThread.getLooper()) {
Log.e(TAG, "playNextDataSource: called on wrong looper");
}
@@ -1013,24 +1013,6 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
private native final void _seekTo(long msec, int mode);
- /**
- * Get current playback position as a {@link MediaTimestamp}.
- * <p>
- * The MediaTimestamp represents how the media time correlates to the system time in
- * a linear fashion using an anchor and a clock rate. During regular playback, the media
- * time moves fairly constantly (though the anchor frame may be rebased to a current
- * system time, the linear correlation stays steady). Therefore, this method does not
- * need to be called often.
- * <p>
- * To help users get current playback position, this method always anchors the timestamp
- * to the current {@link System#nanoTime system time}, so
- * {@link MediaTimestamp#getAnchorMediaTimeUs} can be used as current playback position.
- *
- * @return a MediaTimestamp object if a timestamp is available, or {@code null} if no timestamp
- * is available, e.g. because the media player has not been initialized.
- *
- * @see MediaTimestamp
- */
@Override
@Nullable
public MediaTimestamp getTimestamp()
@@ -1046,11 +1028,6 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
}
}
- /**
- * Resets the MediaPlayer2 to its uninitialized state. After calling
- * this method, you will have to initialize it again by setting the
- * data source and calling prepare().
- */
@Override
public void reset() {
synchronized (mEventCbLock) {
@@ -1083,41 +1060,14 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
// Keep KEY_PARAMETER_* in sync with include/media/mediaplayer2.h
private final static int KEY_PARAMETER_AUDIO_ATTRIBUTES = 1400;
- /**
- * Sets the audio attributes.
- * @param value value of the parameter to be set.
- * @return true if the parameter is set successfully, false otherwise
- */
+
+ // return true if the parameter is set successfully, false otherwise
private native boolean native_setAudioAttributes(AudioAttributes audioAttributes);
private native AudioAttributes native_getAudioAttributes();
-
- /**
- * Checks whether the MediaPlayer2 is looping or non-looping.
- *
- * @return true if the MediaPlayer2 is currently looping, false otherwise
- * @hide
- */
@Override
public native boolean isLooping();
- /**
- * Sets the audio session ID.
- *
- * @param sessionId the audio session ID.
- * The audio session ID is a system wide unique identifier for the audio stream played by
- * this MediaPlayer2 instance.
- * The primary use of the audio session ID is to associate audio effects to a particular
- * instance of MediaPlayer2: if an audio session ID is provided when creating an audio effect,
- * this effect will be applied only to the audio content of media players within the same
- * audio session and not to the output mix.
- * When created, a MediaPlayer2 instance automatically generates its own audio session ID.
- * However, it is possible to force this player to be part of an already existing audio session
- * by calling this method.
- * This method must be called before one of the overloaded <code> setDataSource </code> methods.
- * @throws IllegalStateException if it is called in an invalid state
- * @throws IllegalArgumentException if the sessionId is invalid.
- */
@Override
public Object setAudioSessionId(int sessionId) {
return addTask(new Task(CALL_COMPLETED_SET_AUDIO_SESSION_ID, false) {
@@ -1130,29 +1080,9 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
private native void _setAudioSessionId(int sessionId);
- /**
- * Returns the audio session ID.
- *
- * @return the audio session ID. {@see #setAudioSessionId(int)}
- * Note that the audio session ID is 0 only if a problem occured when the MediaPlayer2 was contructed.
- */
@Override
public native int getAudioSessionId();
- /**
- * Attaches an auxiliary effect to the player. A typical auxiliary effect is a reverberation
- * effect which can be applied on any sound source that directs a certain amount of its
- * energy to this effect. This amount is defined by setAuxEffectSendLevel().
- * See {@link #setAuxEffectSendLevel(float)}.
- * <p>After creating an auxiliary effect (e.g.
- * {@link android.media.audiofx.EnvironmentalReverb}), retrieve its ID with
- * {@link android.media.audiofx.AudioEffect#getId()} and use it when calling this method
- * to attach the player to the effect.
- * <p>To detach the effect from the player, call this method with a null effect id.
- * <p>This method must be called after one of the overloaded <code> setDataSource </code>
- * methods.
- * @param effectId system wide unique id of the effect to attach
- */
@Override
public Object attachAuxEffect(int effectId) {
return addTask(new Task(CALL_COMPLETED_ATTACH_AUX_EFFECT, false) {
@@ -1165,18 +1095,6 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
private native void _attachAuxEffect(int effectId);
- /**
- * Sets the send level of the player to the attached auxiliary effect.
- * See {@link #attachAuxEffect(int)}. The level value range is 0 to 1.0.
- * <p>By default the send level is 0, so even if an effect is attached to the player
- * this method must be called for the effect to be applied.
- * <p>Note that the passed level value is a raw scalar. UI controls should be scaled
- * logarithmically: the gain applied by audio framework ranges from -72dB to 0dB,
- * so an appropriate conversion from linear UI input x to level is:
- * x == 0 -> level = 0
- * 0 < x <= R -> level = 10^(72*(x-R)/20/R)
- * @param level send level scalar
- */
@Override
public Object setAuxEffectSendLevel(float level) {
return addTask(new Task(CALL_COMPLETED_SET_AUX_EFFECT_SEND_LEVEL, false) {
@@ -1206,31 +1124,17 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
* @see android.media.MediaPlayer2#getTrackInfo
*/
public static final class TrackInfoImpl extends TrackInfo {
- /**
- * Gets the track type.
- * @return TrackType which indicates if the track is video, audio, timed text.
- */
@Override
public int getTrackType() {
return mTrackType;
}
- /**
- * Gets the language code of the track.
- * @return a language code in either way of ISO-639-1 or ISO-639-2.
- * When the language is unknown or could not be determined,
- * ISO-639-2 language code, "und", is returned.
- */
@Override
public String getLanguage() {
String language = mFormat.getString(MediaFormat.KEY_LANGUAGE);
return language == null ? "und" : language;
}
- /**
- * Gets the {@link MediaFormat} of the track. If the format is
- * unknown or could not be determined, null is returned.
- */
@Override
public MediaFormat getFormat() {
if (mTrackType == MEDIA_TRACK_TYPE_TIMEDTEXT
@@ -1292,14 +1196,6 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
}
};
- /**
- * Returns a List of track information.
- *
- * @return List of track info. The total number of tracks is the array length.
- * Must be called again if an external timed text source has been added after
- * addTimedTextSource method is called.
- * @throws IllegalStateException if it is called in an invalid state.
- */
@Override
public List<TrackInfo> getTrackInfo() {
TrackInfoImpl trackInfo[] = getInbandTrackInfoImpl();
@@ -1326,33 +1222,6 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
return trackInfo;
}
- /*
- * A helper function to check if the mime type is supported by media framework.
- */
- private static boolean availableMimeTypeForExternalSource(String mimeType) {
- if (MEDIA_MIMETYPE_TEXT_SUBRIP.equals(mimeType)) {
- return true;
- }
- return false;
- }
-
- /**
- * Returns the index of the audio, video, or subtitle track currently selected for playback,
- * The return value is an index into the array returned by {@link #getTrackInfo()}, and can
- * be used in calls to {@link #selectTrack(int)} or {@link #deselectTrack(int)}.
- *
- * @param trackType should be one of {@link TrackInfo#MEDIA_TRACK_TYPE_VIDEO},
- * {@link TrackInfo#MEDIA_TRACK_TYPE_AUDIO}, or
- * {@link TrackInfo#MEDIA_TRACK_TYPE_SUBTITLE}
- * @return index of the audio, video, or subtitle track currently selected for playback;
- * a negative integer is returned when there is no selected track for {@code trackType} or
- * when {@code trackType} is not one of audio, video, or subtitle.
- * @throws IllegalStateException if called after {@link #close()}
- *
- * @see #getTrackInfo()
- * @see #selectTrack(int)
- * @see #deselectTrack(int)
- */
@Override
public int getSelectedTrack(int trackType) {
PlayerMessage request = PlayerMessage.newBuilder()
@@ -1366,34 +1235,6 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
return response.getValues(0).getInt32Value();
}
- /**
- * Selects a track.
- * <p>
- * If a MediaPlayer2 is in invalid state, it throws an IllegalStateException exception.
- * If a MediaPlayer2 is in <em>Started</em> state, the selected track is presented immediately.
- * If a MediaPlayer2 is not in Started state, it just marks the track to be played.
- * </p>
- * <p>
- * In any valid state, if it is called multiple times on the same type of track (ie. Video,
- * Audio, Timed Text), the most recent one will be chosen.
- * </p>
- * <p>
- * The first audio and video tracks are selected by default if available, even though
- * this method is not called. However, no timed text track will be selected until
- * this function is called.
- * </p>
- * <p>
- * Currently, only timed text tracks or audio tracks can be selected via this method.
- * In addition, the support for selecting an audio track at runtime is pretty limited
- * in that an audio track can only be selected in the <em>Prepared</em> state.
- * </p>
- * @param index the index of the track to be selected. The valid range of the index
- * is 0..total number of track - 1. The total number of tracks as well as the type of
- * each individual track can be found by calling {@link #getTrackInfo()} method.
- * @throws IllegalStateException if called in an invalid state.
- *
- * @see android.media.MediaPlayer2#getTrackInfo
- */
@Override
public Object selectTrack(int index) {
return addTask(new Task(CALL_COMPLETED_SELECT_TRACK, false) {
@@ -1404,20 +1245,6 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
});
}
- /**
- * Deselect a track.
- * <p>
- * Currently, the track must be a timed text track and no audio or video tracks can be
- * deselected. If the timed text track identified by index has not been
- * selected before, it throws an exception.
- * </p>
- * @param index the index of the track to be deselected. The valid range of the index
- * is 0..total number of tracks - 1. The total number of tracks as well as the type of
- * each individual track can be found by calling {@link #getTrackInfo()} method.
- * @throws IllegalStateException if called in an invalid state.
- *
- * @see android.media.MediaPlayer2#getTrackInfo
- */
@Override
public Object deselectTrack(int index) {
return addTask(new Task(CALL_COMPLETED_DESELECT_TRACK, false) {
diff --git a/media/java/android/media/MediaPlayer2Utils.java b/media/java/android/media/MediaPlayer2Utils.java
new file mode 100644
index 000000000000..c6dee22813a0
--- /dev/null
+++ b/media/java/android/media/MediaPlayer2Utils.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * Helper class used by native code to reduce JNI calls from native side.
+ * @hide
+ */
+public class MediaPlayer2Utils {
+ /**
+ * Returns whether audio offloading is supported for the given audio format.
+ *
+ * @param encoding the type of encoding defined in {@link AudioFormat}
+ * @param sampleRate the sampling rate of the stream
+ * @param channelMask the channel mask defined in {@link AudioFormat}
+ */
+ // @CalledByNative
+ public static boolean isOffloadedAudioPlaybackSupported(
+ int encoding, int sampleRate, int channelMask) {
+ final AudioFormat format = new AudioFormat.Builder()
+ .setEncoding(encoding)
+ .setSampleRate(sampleRate)
+ .setChannelMask(channelMask)
+ .build();
+ return AudioManager.isOffloadedPlaybackSupported(format);
+ }
+}
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index 0769e5c84674..c49e720fa6ad 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -1050,9 +1050,9 @@ android_media_MediaPlayer2_native_finalize(JNIEnv *env, jobject thiz)
android_media_MediaPlayer2_release(env, thiz);
}
-static void android_media_MediaPlayer2_set_audio_session_id(JNIEnv *env, jobject thiz,
+static void android_media_MediaPlayer2_setAudioSessionId(JNIEnv *env, jobject thiz,
jint sessionId) {
- ALOGV("set_session_id(): %d", sessionId);
+ ALOGV("setAudioSessionId(): %d", sessionId);
sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
if (mp == NULL ) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
@@ -1062,8 +1062,8 @@ static void android_media_MediaPlayer2_set_audio_session_id(JNIEnv *env, jobjec
NULL);
}
-static jint android_media_MediaPlayer2_get_audio_session_id(JNIEnv *env, jobject thiz) {
- ALOGV("get_session_id()");
+static jint android_media_MediaPlayer2_getAudioSessionId(JNIEnv *env, jobject thiz) {
+ ALOGV("getAudioSessionId()");
sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
if (mp == NULL ) {
jniThrowException(env, "java/lang/IllegalStateException", NULL);
@@ -1419,8 +1419,8 @@ static const JNINativeMethod gMethods[] = {
{"native_init", "()V", (void *)android_media_MediaPlayer2_native_init},
{"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer2_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaPlayer2_native_finalize},
- {"getAudioSessionId", "()I", (void *)android_media_MediaPlayer2_get_audio_session_id},
- {"_setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer2_set_audio_session_id},
+ {"getAudioSessionId", "()I", (void *)android_media_MediaPlayer2_getAudioSessionId},
+ {"_setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer2_setAudioSessionId},
{"_setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer2_setAuxEffectSendLevel},
{"_attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer2_attachAuxEffect},
// Modular DRM
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index 942614815c3d..942eafdbc48d 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -37,6 +37,7 @@ cc_library_shared {
ldflags: ["-Wl,--hash-style=both"],
},
},
+ version_script: "libjnigraphics.map.txt",
}
// The headers module is in frameworks/native/Android.bp.
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index 9ecaa03d6e53..5ab66324930d 100644
--- a/packages/CaptivePortalLogin/AndroidManifest.xml
+++ b/packages/CaptivePortalLogin/AndroidManifest.xml
@@ -26,7 +26,8 @@
<uses-permission android:name="android.permission.NETWORK_SETTINGS" />
<application android:label="@string/app_name"
- android:usesCleartextTraffic="true">
+ android:usesCleartextTraffic="true"
+ android:supportsRtl="true" >
<activity
android:name="com.android.captiveportallogin.CaptivePortalLoginActivity"
android:label="@string/action_bar_label"
diff --git a/packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml b/packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml
new file mode 100644
index 000000000000..d460041e59ae
--- /dev/null
+++ b/packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/ssl_error_msg"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:layout_marginStart="20dip"
+ android:layout_marginEnd="20dip"
+ android:gravity="center_vertical"
+ android:layout_marginBottom="4dip"
+ android:layout_marginTop="4dip" />
+
diff --git a/packages/CaptivePortalLogin/res/layout/ssl_warning.xml b/packages/CaptivePortalLogin/res/layout/ssl_warning.xml
new file mode 100644
index 000000000000..ffd57a430662
--- /dev/null
+++ b/packages/CaptivePortalLogin/res/layout/ssl_warning.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <!-- ssl error type -->
+ <TextView
+ android:id="@+id/ssl_error_type"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start"
+ android:text="SSL_UNKNOWN"
+ android:layout_marginStart="24dip"
+ android:layout_marginEnd="24dip"
+ android:layout_marginBottom="0dip"
+ android:layout_marginTop="24dip" />
+
+ <!-- Page info: -->
+ <TextView
+ android:id="@+id/page_info"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/page_info"
+ android:textStyle="bold"
+ android:layout_marginStart="24dip"
+ android:layout_marginEnd="24dip" />
+
+ <!-- Title: -->
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textStyle="bold"
+ android:layout_marginStart="24dip"
+ android:layout_marginEnd="24dip" />
+
+ <!-- Address: -->
+ <TextView
+ android:id="@+id/address_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/page_info_address"
+ android:layout_marginStart="24dip"
+ android:layout_marginEnd="24dip" />
+
+ <TextView
+ android:id="@+id/address"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="24dip"
+ android:layout_marginEnd="24dip" />
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dip"
+ android:paddingEnd="4dip" >
+
+ <!-- certificate view: -->
+ <LinearLayout
+ android:id="@+id/certificate_layout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="16dip" >
+ </LinearLayout>
+
+ </ScrollView>
+
+</LinearLayout>
diff --git a/packages/CaptivePortalLogin/res/values-af/strings.xml b/packages/CaptivePortalLogin/res/values-af/strings.xml
index fa6f3fae2e33..cf4dc824f597 100644
--- a/packages/CaptivePortalLogin/res/values-af/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-af/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Die netwerk waarby jy probeer aansluit, het sekuriteitkwessies."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Byvoorbeeld, die aanmeldbladsy behoort dalk nie aan die organisasie wat gewys word nie."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Gaan in elk geval deur blaaier voort"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Bladsy-inligting"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sekuriteitswaarskuwing"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Bekyk sertifikaat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Hierdie sertifikaat is nie van \'n betroubare owerheid nie."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Die naam van die werf kom nie ooreen met die naam op die sertifikaat nie."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Hierdie sertifikaat het verval."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Hierdie sertifikaat is nog nie geldig nie."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Hierdie sertifikaat het \'n ongeldige datum."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Hierdie sertifikaat is ongeldig."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Onbekende sertifikaatfout."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-am/strings.xml b/packages/CaptivePortalLogin/res/values-am/strings.xml
index 36d5e19d8a84..cdcb5a54daed 100644
--- a/packages/CaptivePortalLogin/res/values-am/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-am/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"ለመቀላቀል እየሞከሩ ያሉት አውታረ መረብ የደህንነት ችግሮች አሉበት።"</string>
<string name="ssl_error_example" msgid="647898534624078900">"ለምሳሌ፣ የመግቢያ ገጹ የሚታየው ድርጅት ላይሆን ይችላል።"</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"ለማንኛውም በአሳሽ በኩል ይቀጥሉ"</string>
+ <string name="ok" msgid="1509280796718850364">"እሺ"</string>
+ <string name="page_info" msgid="4048529256302257195">"የገፅ መረጃ"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"አድራሻ:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"የደህንነት ቅንብሮች"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"ምስክሮች ይመልከቱ"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"ይህ ምስክር ከታማኝ ቦታ አይደለም።"</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"የጣቢያው ስም ከምስክር ወረቀቱ ስም ጋር አይዛመድም።"</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"ይህ ምስክር ጊዜው አልፏል"</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"ይህ ምስክር ገና ትክክል አይደለም።"</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"ይህ ምስክር ትክክለኛ ቀን አለው።"</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"ይህ ምስክር ትክክል ያልሆነ ነው።"</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"ያልታወቀ የምስክር ስህተት።"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-ar/strings.xml b/packages/CaptivePortalLogin/res/values-ar/strings.xml
index 8eb259b57b77..7773eeb22e04 100644
--- a/packages/CaptivePortalLogin/res/values-ar/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ar/strings.xml
@@ -11,4 +11,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"الشبكة التي تحاول الانضمام إليها بها مشاكل أمنية."</string>
<string name="ssl_error_example" msgid="647898534624078900">"على سبيل المثال، قد لا تنتمي صفحة تسجيل الدخول إلى المنظمة المعروضة."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"المتابعة على أي حال عبر المتصفح"</string>
+ <string name="ok" msgid="1509280796718850364">"موافق"</string>
+ <string name="page_info" msgid="4048529256302257195">"معلومات الصفحة"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"العنوان:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"تحذير أمان"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"عرض الشهادة"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"هذه الشهادة ليست من جهة موثوق بها."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"لا يتطابق اسم الموقع مع الاسم على الشهادة."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"انتهت صلاحية هذه الشهادة."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"هذه الشهادة ليست صالحة بعد."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"تشتمل هذه الشهادة على تاريخ غير صالح."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"هذه الشهادة غير صالحة."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"حدث خطأ غير معروف بالشهادة."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-bg/strings.xml b/packages/CaptivePortalLogin/res/values-bg/strings.xml
index 8ce9deb1eb78..4dd8aa0c536c 100644
--- a/packages/CaptivePortalLogin/res/values-bg/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-bg/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Мрежата, към която опитвате да се присъедините, има проблеми със сигурността."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Например страницата за вход може да не принадлежи на показаната организация."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Продължаване през браузър въпреки това"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Данни за страницата"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Адрес:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Предупреждение относно защитата"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Преглед на сертификата"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Сертификатът не е от надежден орган."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Името на сайта не съответства на името в сертификата."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Сертификатът е изтекъл."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Сертификатът още не е валиден."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Този сертификат е с невалидна дата."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Този сертификат е невалиден."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Неизвестна грешка в сертификата."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-bn/strings.xml b/packages/CaptivePortalLogin/res/values-bn/strings.xml
index b75d76e69f7c..fb703cfaadc9 100644
--- a/packages/CaptivePortalLogin/res/values-bn/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-bn/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"আপনি যে নেটওয়ার্কে যোগ দেওয়ার চেষ্টা করছেন তাতে নিরাপত্তার সমস্যা আছে।"</string>
<string name="ssl_error_example" msgid="647898534624078900">"উদাহরণস্বরূপ, লগ-ইন পৃষ্ঠাটি প্রদর্শিত প্রতিষ্ঠানের অন্তর্গত নাও হতে পারে৷"</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"যাই হোক না কেন ব্রাউজারের মাধ্যমে অবিরত রাখুন"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Sideinfo"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sikkerhetsadvarsel"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Vis sertifikat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Sertifikatet er ikke fra en pålitelig myndighet."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Navnet på nettstedet samsvarer ikke med navnet på sertifikatet."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Sertifikatet er utløpt."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Sertifikatet er ikke gyldig ennå."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dette sertifikatet har en ugyldig dato."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Dette sertifikatet er ugyldig."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Ukjent sertifikatfeil."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-ca/strings.xml b/packages/CaptivePortalLogin/res/values-ca/strings.xml
index fe189edaf311..a2c9ed809ba3 100644
--- a/packages/CaptivePortalLogin/res/values-ca/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ca/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"La xarxa a què et vols connectar té problemes de seguretat."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Per exemple, la pàgina d\'inici de sessió podria no pertànyer a l\'organització que es mostra."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continua igualment mitjançant el navegador"</string>
+ <string name="ok" msgid="1509280796718850364">"D\'acord"</string>
+ <string name="page_info" msgid="4048529256302257195">"Informació de la pàgina"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adreça:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Advertiment de seguretat"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Visualitza el certificat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Aquest certificat no és d\'una autoritat de confiança."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"El nom del lloc no coincideix amb el del certificat."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Aquest certificat ha caducat."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Aquest certificat encara no és vàlid."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Aquest certificat té una data no vàlida."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Aquest certificat no és vàlid."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Error de certificat desconegut."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-cs/strings.xml b/packages/CaptivePortalLogin/res/values-cs/strings.xml
index 09dcc5f5989f..be649a50f26c 100644
--- a/packages/CaptivePortalLogin/res/values-cs/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-cs/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Síť, ke které se pokoušíte připojit, má bezpečnostní problémy."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Například přihlašovací stránka nemusí patřit do zobrazované organizace."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Přesto pokračovat prostřednictvím prohlížeče"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Informace o stránce"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresa:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Upozornění zabezpečení"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Zobrazit certifikát"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Tento certifikát nepochází od důvěryhodné autority."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Název webu se neshoduje s názvem uvedeným v certifikátu."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Platnost certifikátu vypršela."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Tento certifikát ještě není platný."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Datum tohoto certifikátu není platné."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Tento certifikát je neplatný."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Neznámá chyba certifikátu."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-da/strings.xml b/packages/CaptivePortalLogin/res/values-da/strings.xml
index dc0dd17c0bf4..8183105a1aff 100644
--- a/packages/CaptivePortalLogin/res/values-da/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-da/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Der er sikkerhedsproblemer på det netværk, du forsøger at logge ind på."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Det er f.eks. ikke sikkert, at loginsiden tilhører den anførte organisation."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Fortsæt alligevel via browseren"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Sideoplysninger"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sikkerhedsadvarsel"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Vis certifikat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Dette certifikat stammer ikke fra en troværdig autoritet."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Navnet på websitet stemmer ikke overens med navnet på certifikatet."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Dette certifikat er udløbet."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Dette certifikat er endnu ikke gyldigt."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dette certifikat har en ugyldig dato."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Dette certifikat er ugyldigt."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Ukendt fejl i certifikatet."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-de/strings.xml b/packages/CaptivePortalLogin/res/values-de/strings.xml
index d8f7be991846..a9b7415d8427 100644
--- a/packages/CaptivePortalLogin/res/values-de/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-de/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Im Netzwerk, zu dem du eine Verbindung herstellen möchtest, liegen Sicherheitsprobleme vor."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Beispiel: Die Log-in-Seite gehört eventuell nicht zur angezeigten Organisation."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Trotzdem in einem Browser fortfahren"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Seiteninfo"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sicherheitswarnung"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Zertifikat ansehen"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Dieses Zertifikat wurde nicht von einer vertrauenswürdigen Stelle ausgegeben."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Name der Website stimmt nicht mit dem Namen auf dem Zertifikat überein."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Dieses Zertifikat ist abgelaufen."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Dieses Zertifikat ist noch nicht gültig."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dieses Zertifikat weist ein ungültiges Datum auf."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Dieses Zertifikat ist ungültig."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Unbekannter Zertifikatfehler"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-el/strings.xml b/packages/CaptivePortalLogin/res/values-el/strings.xml
index cb6171093f12..16bf6e22761d 100644
--- a/packages/CaptivePortalLogin/res/values-el/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-el/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Παρουσιάζονται προβλήματα ασφάλειας στο δίκτυο στο οποίο προσπαθείτε να συνδεθείτε."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Για παράδειγμα, η σελίδα σύνδεσης ενδέχεται να μην ανήκει στον οργανισμό που εμφανίζεται."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Συνέχεια ούτως ή άλλως μέσω του προγράμματος περιήγησης"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Πληροφορίες σελίδας"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Διεύθυνση:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Προειδοποίηση ασφαλείας"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Προβολή πιστοποιητικού"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Αυτό το πιστοποιητικό δεν προέρχεται από αξιόπιστη αρχή."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Το όνομα του ιστότοπου δεν αντιστοιχεί με το όνομα στο πιστοποιητικό."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Αυτό το πιστοποιητικό έχει λήξει."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Αυτό το πιστοποιητικό δεν είναι έγκυρο ακόμα."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Αυτό το πιστοποιητικό δεν έχει έγκυρη ημερομηνία."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Αυτό το πιστοποιητικό δεν είναι έγκυρο."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Άγνωστο σφάλμα πιστοποιητικού."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml b/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
index 2e8d1f082d1f..f940299af6a8 100644
--- a/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"The network that you’re trying to join has security issues."</string>
<string name="ssl_error_example" msgid="647898534624078900">"For example, the login page might not belong to the organisation shown."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continue anyway via browser"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Page info"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Address:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Security warning"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"View certificate"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"This certificate isn\'t from a trusted authority."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"The name of the site doesn\'t match the name on the certificate."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"This certificate has expired."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"This certificate isn\'t valid yet."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"This certificate has an invalid date."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"This certificate is invalid."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Unknown certificate error."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml b/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
index 2e8d1f082d1f..f940299af6a8 100644
--- a/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"The network that you’re trying to join has security issues."</string>
<string name="ssl_error_example" msgid="647898534624078900">"For example, the login page might not belong to the organisation shown."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continue anyway via browser"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Page info"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Address:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Security warning"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"View certificate"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"This certificate isn\'t from a trusted authority."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"The name of the site doesn\'t match the name on the certificate."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"This certificate has expired."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"This certificate isn\'t valid yet."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"This certificate has an invalid date."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"This certificate is invalid."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Unknown certificate error."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-es-rUS/strings.xml b/packages/CaptivePortalLogin/res/values-es-rUS/strings.xml
index 5d7ba9163895..c01166474074 100644
--- a/packages/CaptivePortalLogin/res/values-es-rUS/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-es-rUS/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"La red a la que intentas conectarte tiene problemas de seguridad."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Por ejemplo, es posible que la página de acceso no pertenezca a la organización que aparece."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continuar de todos modos desde el navegador"</string>
+ <string name="ok" msgid="1509280796718850364">"Aceptar"</string>
+ <string name="page_info" msgid="4048529256302257195">"Información de la página"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Dirección:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Advertencia de seguridad"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Ver certificado"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Este certificado no proviene de una autoridad confiable."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"El nombre del sitio no coincide con el nombre del certificado."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Este certificado ha expirado."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Este certificado aún no es válido."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"La fecha de este certificado no es válida."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Este certificado no es válido."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Error de certificado desconocido"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-es/strings.xml b/packages/CaptivePortalLogin/res/values-es/strings.xml
index da2eae9038bf..65244e7e9156 100644
--- a/packages/CaptivePortalLogin/res/values-es/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-es/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"La red a la que intentas unirte tiene problemas de seguridad."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Por ejemplo, es posible que la página de inicio de sesión no pertenezca a la organización mostrada."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continuar de todos modos a través del navegador"</string>
+ <string name="ok" msgid="1509280796718850364">"Aceptar"</string>
+ <string name="page_info" msgid="4048529256302257195">"Información de la página"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Dirección:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Advertencia de seguridad"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Ver certificado"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Este certificado no procede de una entidad de certificación de confianza."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"El nombre del sitio no coincide con el del certificado."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Este certificado ha caducado."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Este certificado aún no es válido."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"La fecha de este certificado no es válida."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Este certificado no es válido."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Error de certificado desconocido"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-et/strings.xml b/packages/CaptivePortalLogin/res/values-et/strings.xml
index 41fcb9a6bd6a..e4c4c9801d5c 100644
--- a/packages/CaptivePortalLogin/res/values-et/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-et/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Võrgul, millega üritate ühenduse luua, on turvaprobleeme."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Näiteks ei pruugi sisselogimisleht kuuluda kuvatavale organisatsioonile."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Jätka siiski brauseris"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Lehe teave"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Aadress:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Turvahoiatus"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Kuva sertifikaat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"See sertifikaat ei pärine usaldusväärselt asutuselt."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Saidi nimi ei vasta sertifikaadil olevale nimele."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"See sertifikaat on aegunud."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"See sertifikaat pole veel kehtiv."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Sellel sertifikaadil on kehtetu kuupäev."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"See sertifikaat on kehtetu."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Tundmatu sertifikaadiviga."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-fa/strings.xml b/packages/CaptivePortalLogin/res/values-fa/strings.xml
index 2e4cc5134e1b..27b9b7f15fab 100644
--- a/packages/CaptivePortalLogin/res/values-fa/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-fa/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"شبکه‌ای که می‌خواهید به آن بپیوندید مشکلات امنیتی دارد."</string>
<string name="ssl_error_example" msgid="647898534624078900">"به عنوان مثال، صفحه ورود به سیستم ممکن است متعلق به سازمان نشان داده شده نباشد."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"در هر صورت از طریق مرورگر ادامه یابد"</string>
+ <string name="ok" msgid="1509280796718850364">"تأیید"</string>
+ <string name="page_info" msgid="4048529256302257195">"اطلاعات صفحه"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"آدرس:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"اخطار امنیتی"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"مشاهده گواهی"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"این گواهی از یک منبع مورد اطمینان صادر نشده است."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"نام سایت با نام موجود در گواهی مطابقت ندارد."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"این گواهی منقضی شده است."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"این گواهی هنوز معتبر نیست."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"تاریخ این گواهی نامعتبر است."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"این گواهی نامعتبر است."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"خطای ناشناخته در گواهی."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-fi/strings.xml b/packages/CaptivePortalLogin/res/values-fi/strings.xml
index 1976f7d1c1e6..8086fbf96088 100644
--- a/packages/CaptivePortalLogin/res/values-fi/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-fi/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Verkossa, johon yrität muodostaa yhteyttä, on turvallisuusongelmia."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Kirjautumissivu ei välttämättä kuulu näytetylle organisaatiolle."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Jatka silti selaimen kautta."</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Sivun tiedot"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Osoite:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Suojausvaroitus"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Näytä varmenne"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Varmenteen myöntäjä ei ole luotettava taho."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Sivuston nimi ei vastaa varmenteessa olevaa nimeä."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Varmenne ei ole enää voimassa."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Varmenne ei ole vielä voimassa."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Varmenteen päiväys ei kelpaa."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Varmenne on virheellinen."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Tuntematon varmennevirhe."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-fr/strings.xml b/packages/CaptivePortalLogin/res/values-fr/strings.xml
index 8f98bb5131ca..39fc5692bc21 100644
--- a/packages/CaptivePortalLogin/res/values-fr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-fr/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Le réseau que vous essayez de rejoindre présente des problèmes de sécurité."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Par exemple, la page de connexion peut ne pas appartenir à l\'organisation représentée."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continuer quand même dans le navigateur"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Infos sur la page"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresse :"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Avertissement de sécurité"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Afficher le certificat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Ce certificat provient d\'une autorité non approuvée."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Le nom du site ne correspond pas au nom indiqué dans le certificat."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Le certificat a expiré."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Ce certificat n\'est pas encore valide."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"La date de ce certificat n\'est pas valide."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Ce certificat n\'est pas valide."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Erreur : Certificat inconnu."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-hi/strings.xml b/packages/CaptivePortalLogin/res/values-hi/strings.xml
index 1bacc4680f1c..d924fffb8c1a 100644
--- a/packages/CaptivePortalLogin/res/values-hi/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-hi/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"आप जिस नेटवर्क में शामिल होने का प्रयास कर रहे हैं उसमें सुरक्षा समस्‍याएं हैं."</string>
<string name="ssl_error_example" msgid="647898534624078900">"उदाहरण के लिए, हो सकता है कि लॉगिन पृष्‍ठ दिखाए गए संगठन से संबद्ध ना हो."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"ब्राउज़र के द्वारा फिर जारी रखें"</string>
+ <string name="ok" msgid="1509280796718850364">"ठीक"</string>
+ <string name="page_info" msgid="4048529256302257195">"पृष्ठ जानकारी"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"पता:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"सुरक्षा चेतावनी"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"प्रमाणपत्र देखें"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"यह प्रमाणपत्र किसी विश्वस्त प्राधिकारी का नहीं है."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"साइट का नाम, प्रमाणपत्र के नाम से मिलान नहीं करता."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"इस प्रमाणपत्र की समय सीमा समाप्त हो गई है."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"यह प्रमाणपत्र अभी तक मान्य नहीं है."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"इस प्रमाणपत्र में एक अमान्‍य दिनांक है."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"यह प्रमाणपत्र अमान्य है."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"अज्ञात प्रमाणपत्र त्रुटि."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-hr/strings.xml b/packages/CaptivePortalLogin/res/values-hr/strings.xml
index e44cd3b22cf2..11b1dd3f50e9 100644
--- a/packages/CaptivePortalLogin/res/values-hr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-hr/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Mreža kojoj se pokušavate pridružiti ima sigurnosne poteškoće."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Na primjer, stranica za prijavu možda ne pripada prikazanoj organizaciji."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Ipak nastavi putem preglednika"</string>
+ <string name="ok" msgid="1509280796718850364">"U redu"</string>
+ <string name="page_info" msgid="4048529256302257195">"Informacije o stranici"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresa:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Upozorenje o sigurnosti"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Prikaži certifikat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Ovaj certifikat ne potječe iz pouzdanog izvora."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Naziv web-lokacije ne podudara se s nazivom na certifikatu."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Ovaj je certifikat istekao."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Ovaj certifikat još nije važeći."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Ovaj certifikat ima nevažeći datum."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Ovaj certifikat nije valjan."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Nepoznata pogreška certifikata."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-hu/strings.xml b/packages/CaptivePortalLogin/res/values-hu/strings.xml
index f15fb49634e1..145e2abd0906 100644
--- a/packages/CaptivePortalLogin/res/values-hu/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-hu/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Biztonsági problémák vannak azzal a hálózattal, amelyhez csatlakozni szeretne."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Például lehet, hogy a bejelentkezési oldal nem a megjelenített szervezethez tartozik."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Folytatás ennek ellenére böngészőn keresztül"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Oldaladatok"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Cím:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Biztonsági figyelmeztetés"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Tanúsítvány megtekintése"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Ez a tanúsítvány nem hiteles tanúsítványkibocsátótól származik."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"A webhely neve nem egyezik a tanúsítványon lévő névvel."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"A tanúsítvány lejárt."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"A tanúsítvány még nem érvényes."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"A tanúsítvány dátuma érvénytelen."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Ez a tanúsítvány érvénytelen."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Ismeretlen tanúsítványhiba."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-in/strings.xml b/packages/CaptivePortalLogin/res/values-in/strings.xml
index 10e3de6b9f24..4a335dd38979 100644
--- a/packages/CaptivePortalLogin/res/values-in/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-in/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Jaringan yang ingin Anda masuki mengalami masalah keamanan."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Misalnya, halaman masuk mungkin bukan milik organisasi yang ditampilkan."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Tetap lanjutkan melalui browser"</string>
+ <string name="ok" msgid="1509280796718850364">"Oke"</string>
+ <string name="page_info" msgid="4048529256302257195">"Info laman"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Alamat:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Peringatan sertifikat"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Lihat sertifikat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Sertifikat ini tidak berasal dari otoritas tepercaya."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Nama situs tidak cocok dengan nama pada sertifikat."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Sertifikat ini telah kedaluwarsa."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Sertifikat ini belum valid."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Tanggal sertifikat ini tidak valid."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Sertifikat ini tidak valid."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Kesalahan sertifikat tak dikenal."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-it/strings.xml b/packages/CaptivePortalLogin/res/values-it/strings.xml
index a01a55339da4..2cc4038fbe63 100644
--- a/packages/CaptivePortalLogin/res/values-it/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-it/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"La rete a cui stai tentando di accedere presenta problemi di sicurezza."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Ad esempio, la pagina di accesso potrebbe non appartenere all\'organizzazione indicata."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continua comunque dal browser"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Info pagina"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Indirizzo:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Avviso di sicurezza"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Visualizza certificato"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Questo certificato non proviene da un\'autorità attendibile."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Il nome del sito non corrisponde al nome nel certificato."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Il certificato è scaduto."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Questo certificato non è ancora valido."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Questo certificato presenta una data non valida."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Questo certificato non è valido."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Errore certificato sconosciuto."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-iw/strings.xml b/packages/CaptivePortalLogin/res/values-iw/strings.xml
index 8e7915d83cc6..527e69247104 100644
--- a/packages/CaptivePortalLogin/res/values-iw/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-iw/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"יש בעיות אבטחה ברשת שאליה אתה מנסה להתחבר."</string>
<string name="ssl_error_example" msgid="647898534624078900">"לדוגמה, ייתכן שדף ההתחברות אינו שייך לארגון המוצג."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"המשך בכל זאת באמצעות דפדפן"</string>
+ <string name="ok" msgid="1509280796718850364">"אישור"</string>
+ <string name="page_info" msgid="4048529256302257195">"פרטי דף"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"כתובת:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"אזהרת אבטחה"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"הצג אישור"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"אישור זה אינו מגיע מרשות אמינה."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"שם האתר לא תואם לשם באישור."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"פג תוקפו של אישור זה."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"אישור זה אינו חוקי עדיין."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"לאישור זה יש תאריך בלתי חוקי."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"אישור זה אינו חוקי."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"שגיאת אישור לא ידועה."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-ja/strings.xml b/packages/CaptivePortalLogin/res/values-ja/strings.xml
index e275b95849c1..bcc8686f8c65 100644
--- a/packages/CaptivePortalLogin/res/values-ja/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ja/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"接続しようとしているネットワークにセキュリティの問題があります。"</string>
<string name="ssl_error_example" msgid="647898534624078900">"たとえば、ログインページが表示されている組織に属していない可能性があります。"</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"ブラウザから続行"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"ページ情報"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"アドレス:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"セキュリティ警告"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"証明書を表示"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"この証明書は信頼できる認証機関のものではありません。"</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"サイト名と証明書上の名前が一致しません。"</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"この証明書は有効期限切れです。"</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"この証明書はまだ有効ではありません。"</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"この証明書の日付は無効です。"</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"この証明書は無効です。"</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"不明な証明書エラーです。"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-ko/strings.xml b/packages/CaptivePortalLogin/res/values-ko/strings.xml
index 75f2b48d98c2..7a7f7e075b30 100644
--- a/packages/CaptivePortalLogin/res/values-ko/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ko/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"가입하려는 네트워크에 보안 문제가 있습니다."</string>
<string name="ssl_error_example" msgid="647898534624078900">"예를 들어 로그인 페이지가 표시된 조직에 속하지 않을 수 있습니다."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"브라우저를 통해 계속하기"</string>
+ <string name="ok" msgid="1509280796718850364">"확인"</string>
+ <string name="page_info" msgid="4048529256302257195">"페이지 정보"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"주소:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"보안 경고"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"인증서 보기"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"신뢰할 수 있는 인증 기관에서 발급한 인증서가 아닙니다."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"사이트 이름이 인증서에 있는 것과 일치하지 않습니다."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"인증서가 만료되었습니다."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"인증서가 아직 유효하지 않습니다."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"인증서 날짜가 유효하지 않습니다."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"인증서가 잘못되었습니다."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"알 수 없는 인증서 오류입니다."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-lt/strings.xml b/packages/CaptivePortalLogin/res/values-lt/strings.xml
index 17da83fd15ce..158f7cea00d8 100644
--- a/packages/CaptivePortalLogin/res/values-lt/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-lt/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Kilo tinklo, prie kurio bandote prisijungti, problemų."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Pavyzdžiui, prisijungimo puslapis gali nepriklausyti rodomai organizacijai."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Vis tiek tęsti naudojant naršyklę"</string>
+ <string name="ok" msgid="1509280796718850364">"Gerai"</string>
+ <string name="page_info" msgid="4048529256302257195">"Puslapio informacija"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresas:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Saugos įspėjimas"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Žiūrėti sertifikatą"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Šį sertifikatą išdavė nepatikima įstaiga."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Svetainės pavadinimas neatitinka sertifikate nurodyto pavadinimo."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Šio sertifikato galiojimo laikas baigėsi."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Šis sertifikatas dar negalioja."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Šio sertifikato data netinkama."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Šis sertifikatas netinkamas."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Nežinoma sertifikato klaida."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-lv/strings.xml b/packages/CaptivePortalLogin/res/values-lv/strings.xml
index 95b855884c11..a42cb220a0d1 100644
--- a/packages/CaptivePortalLogin/res/values-lv/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-lv/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Tīklam, kuram mēģināt pievienoties, ir drošības problēmas."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Piemēram, pieteikšanās lapa, iespējams, nepieder norādītajai organizācijai."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Tik un tā turpināt, izmantojot pārlūkprogrammu"</string>
+ <string name="ok" msgid="1509280796718850364">"Labi"</string>
+ <string name="page_info" msgid="4048529256302257195">"Lapas informācija"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adrese:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Drošības brīdinājums"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Skatīt sertifikātu"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Šo sertifikātu nav izsniegusi uzticama iestāde."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Vietnes nosaukums neatbilst nosaukumam sertifikātā."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Šī sertifikāta derīguma termiņš ir beidzies."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Šis sertifikāts vēl nav derīgs."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Šī sertifikāta datums nav derīgs."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Šis sertifikāts nav derīgs."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Nezināma sertifikāta kļūda."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-ms/strings.xml b/packages/CaptivePortalLogin/res/values-ms/strings.xml
index 933721ace248..aaa51c8fbe3f 100644
--- a/packages/CaptivePortalLogin/res/values-ms/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ms/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Rangkaian yang anda cuba sertai mempunyai isu keselamatan."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Contohnya, halaman log masuk mungkin bukan milik organisasi yang ditunjukkan."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Teruskan juga melalui penyemak imbas"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Maklumat halaman"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Alamat:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Amaran keselamatan"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Lihat sijil"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Sijil ini bukan daripada pihak berkuasa yang dipercayai."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Nama tapak tidak sepadan dengan nama pada sijil."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Sijil ini telah tamat tempoh."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Sijil ini belum lagi sah."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Sijil ini mempunyai tarikh yang tidak sah."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Sijil ini tidak sah."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Ralat sijil tidak diketahui."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-nb/strings.xml b/packages/CaptivePortalLogin/res/values-nb/strings.xml
index 0dd5b6ceefa5..29c23ed2ee61 100644
--- a/packages/CaptivePortalLogin/res/values-nb/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-nb/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Nettverket du prøver å logge på, har sikkerhetsproblemer."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Det er for eksempel mulig at påloggingssiden kanskje ikke tilhører organisasjonen som vises."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Fortsett likevel via nettleseren"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Sideinfo"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresse:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Sikkerhetsadvarsel"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Vis sertifikat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Sertifikatet er ikke fra en pålitelig myndighet."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Navnet på nettstedet samsvarer ikke med navnet på sertifikatet."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Sertifikatet er utløpt."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Sertifikatet er ikke gyldig ennå."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dette sertifikatet har en ugyldig dato."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Dette sertifikatet er ugyldig."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Ukjent sertifikatfeil."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-nl/strings.xml b/packages/CaptivePortalLogin/res/values-nl/strings.xml
index 1c5960155f4d..2cbca06c13dd 100644
--- a/packages/CaptivePortalLogin/res/values-nl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-nl/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Het netwerk waarmee u verbinding probeert te maken, heeft beveiligingsproblemen."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Zo hoort de weergegeven inlogpagina misschien niet bij de weergegeven organisatie."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Toch doorgaan via browser"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Pagina-informatie"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Beveiligingsmelding"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Certificaat weergeven"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Dit is geen certificaat van een vertrouwde autoriteit."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"De naam van deze site komt niet overeen met de naam op het certificaat."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Dit certificaat is verlopen."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Dit certificaat is nog niet geldig."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Dit certificaat heeft een ongeldige datum."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Dit certificaat is ongeldig."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Onbekende certificaatfout."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-pl/strings.xml b/packages/CaptivePortalLogin/res/values-pl/strings.xml
index 17f20df33717..9ba066ebb12d 100644
--- a/packages/CaptivePortalLogin/res/values-pl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-pl/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"W sieci, z którą próbujesz się połączyć, występują problemy z zabezpieczeniami."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Na przykład strona logowania może nie należeć do wyświetlanej organizacji."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Kontynuuj mimo to w przeglądarce"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Informacje o stronie"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Ostrzeżenie zabezpieczeń"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Wyświetl certyfikat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Certyfikat nie pochodzi od zaufanego urzędu."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Nazwa witryny nie pasuje do nazwy na certyfikacie."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Ten certyfikat wygasł."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Certyfikat nie jest jeszcze ważny."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Certyfikat ma nieprawidłową datę."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Certyfikat jest nieprawidłowy."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Nieznany błąd certyfikatu"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml b/packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml
index 94b9d60f69da..5bef235af136 100644
--- a/packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-pt-rPT/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"A rede à qual está a tentar aceder tem problemas de segurança."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Por exemplo, a página de início de sessão pode não pertencer à entidade apresentada."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continuar mesmo assim através do navegador"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Informações da página"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Endereço:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Aviso de segurança"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Ver certificado"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Este certificado não pertence a uma autoridade fidedigna."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"O nome do Web site não corresponde ao nome constante no certificado."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Este certificado expirou."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Este certificado ainda não é válido."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Este certificado tem uma data inválida."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Este certificado é inválido."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Erro: certificado desconhecido."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-pt/strings.xml b/packages/CaptivePortalLogin/res/values-pt/strings.xml
index 3d1064cf98d9..ebe4148fcca9 100644
--- a/packages/CaptivePortalLogin/res/values-pt/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-pt/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"A rede à qual você está tentando se conectar tem problemas de segurança."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Por exemplo, a página de login pode não pertencer à organização mostrada."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continuar mesmo assim pelo navegador"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Informações da página"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Endereço:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Aviso de segurança"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Visualizar certificado"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Este certificado não é de uma autoridade confiável."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"O nome do site não corresponde ao nome no certificado."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Este certificado expirou."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Este certificado ainda não é válido."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Este certificado tem uma data inválida."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Este certificado é inválido."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Erro de certificado desconhecido."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-ro/strings.xml b/packages/CaptivePortalLogin/res/values-ro/strings.xml
index cf1b6b5cd478..e2e4eac97876 100644
--- a/packages/CaptivePortalLogin/res/values-ro/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ro/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Rețeaua la care încercați să vă conectați are probleme de securitate."</string>
<string name="ssl_error_example" msgid="647898534624078900">"De exemplu, este posibil ca pagina de conectare să nu aparțină organizației afișate."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Continuați oricum prin browser"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Informaţii pagină"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresă:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Avertisment de securitate"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Vizualizaţi certificatul"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Acest certificat nu provine de la o autoritate de încredere."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Numele acestui site nu se potriveşte cu numele de pe certificat."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Acest certificat a expirat."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Acest certificat nu este încă valid."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Acest certificat are o dată nevalidă."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Acest certificat este nevalid."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Eroare de certificat necunoscută."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-ru/strings.xml b/packages/CaptivePortalLogin/res/values-ru/strings.xml
index 6966bcd69290..c0153e6d7611 100644
--- a/packages/CaptivePortalLogin/res/values-ru/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-ru/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Сеть, к которой вы хотите подключиться, небезопасна."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Например, страница входа в аккаунт может быть фиктивной."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Игнорировать и открыть браузер"</string>
+ <string name="ok" msgid="1509280796718850364">"ОК"</string>
+ <string name="page_info" msgid="4048529256302257195">"Информация о странице"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Адрес:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Угроза безопасности"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Просмотреть сертификат"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Этот сертификат получен из ненадежных источников."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Название сайта не соответствует названию в сертификате."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Срок действия сертификата истек."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Сертификат еще не действителен."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Дата этого сертификата недействительна."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Этот сертификат недействителен."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Неизвестная ошибка сертификата."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-sk/strings.xml b/packages/CaptivePortalLogin/res/values-sk/strings.xml
index 54763be28912..8ba24b1c4ed9 100644
--- a/packages/CaptivePortalLogin/res/values-sk/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sk/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Sieť, ku ktorej sa pokúšate pripojiť, má problémy so zabezpečením"</string>
<string name="ssl_error_example" msgid="647898534624078900">"Napríklad prihlasovacia stránka nemusí patriť uvedenej organizácii."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Pokračovať pomocou prehliadača"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Informácie o stránke"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adresa:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Upozornenie zabezpečenia"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Zobraziť certifikát"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Tento certifikát nepochádza od dôveryhodnej autority."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Názov stránky sa nezhoduje s názvom uvedeným v certifikáte."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Platnosť certifikátu skončila."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Tento certifikát zatiaľ nie je platný."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Tento certifikát má neplatný dátum."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Tento certifikát je neplatný."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Neznáma chyba certifikátu."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-sl/strings.xml b/packages/CaptivePortalLogin/res/values-sl/strings.xml
index 7dd0b374f483..b7d9a8a81b8b 100644
--- a/packages/CaptivePortalLogin/res/values-sl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sl/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Omrežje, ki se mu poskušate pridružiti, ima varnostne težave."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Stran za prijavo na primer morda ne pripada prikazani organizaciji."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Vseeno nadaljuj v brskalniku"</string>
+ <string name="ok" msgid="1509280796718850364">"V redu"</string>
+ <string name="page_info" msgid="4048529256302257195">"Podatki o strani"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Naslov:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Varnostno opozorilo"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Prikaži potrdilo"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Potrdila ni izdal zaupanja vreden overitelj."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Ime spletnega mesta se ne ujema z imenom na potrdilu."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Potrdilo je poteklo."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"To potrdilo še ni veljavno."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Potrdilo ima neveljaven datum."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"To potrdilo ni veljavno."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Neznana napaka potrdila."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-sr/strings.xml b/packages/CaptivePortalLogin/res/values-sr/strings.xml
index f6042897e493..967c8ba87ac1 100644
--- a/packages/CaptivePortalLogin/res/values-sr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sr/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Мрежа којој покушавате да се придружите има безбедносних проблема."</string>
<string name="ssl_error_example" msgid="647898534624078900">"На пример, страница за пријављивање можда не припада приказаној организацији."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Ипак настави преко прегледача"</string>
+ <string name="ok" msgid="1509280796718850364">"Потврди"</string>
+ <string name="page_info" msgid="4048529256302257195">"Информације о страници"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Адреса:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Безбедносно упозорење"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Прикажи сертификат"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Овај сертификат не потиче од поузданог ауторитета."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Назив сајта се не подудара са називом на сертификату."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Овај сертификат је истекао."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Овај сертификат још увек није важећи."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Датум овог сертификата је неважећи."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Овај сертификат је неважећи."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Непозната грешка сертификата."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-sv/strings.xml b/packages/CaptivePortalLogin/res/values-sv/strings.xml
index 8cf70413ef67..75356f01d81f 100644
--- a/packages/CaptivePortalLogin/res/values-sv/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sv/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Nätverket du försöker ansluta till har säkerhetsproblem."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Det kan t.ex. hända att inloggningssidan inte tillhör den organisation som visas."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Fortsätt ändå via webbläsaren"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Sidinformation"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adress:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Säkerhetsvarning"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Visa certifikat"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Certifikatet kommer inte från en betrodd utfärdare."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Webbplatsens namn stämmer inte med namnet på certifikatet."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Certifikatet har upphört att gälla."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Certifikatet är inte giltigt än."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Det här certifikatet har ett ogiltigt datum."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Certifikatet är ogiltigt."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Okänt certifikatfel."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-sw/strings.xml b/packages/CaptivePortalLogin/res/values-sw/strings.xml
index 1c8b6e1c9dcd..feb2ddeba9c1 100644
--- a/packages/CaptivePortalLogin/res/values-sw/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-sw/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Mtandao unaojaribu kujiunga nao una matatizo ya usalama."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Kwa mfano, ukurasa wa kuingia katika akaunti unaweza usiwe unamilikiwa na shirika lililoonyeshwa."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Endelea hata hivyo kupitia kivinjari"</string>
+ <string name="ok" msgid="1509280796718850364">"Sawa"</string>
+ <string name="page_info" msgid="4048529256302257195">"Maelezo ya ukurasa"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Anwani:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Ilani ya usalama"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Tazama cheti"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Cheti hiki hakijatoka kwa mamlaka inayoaminika."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Jina la tovuti halilingani na jina lililo katika cheti."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Cheti hiki kimepitwa na muda"</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Cheti bado si halali."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Cheti hiki kina tarehe batili."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Hati hii ni batili."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Hitilafu isiyojulikana ya cheti."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-th/strings.xml b/packages/CaptivePortalLogin/res/values-th/strings.xml
index 9a3a626d7dbe..11a2131dc64c 100644
--- a/packages/CaptivePortalLogin/res/values-th/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-th/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"เครือข่ายที่คุณพยายามเข้าร่วมมีปัญหาด้านความปลอดภัย"</string>
<string name="ssl_error_example" msgid="647898534624078900">"ตัวอย่างเช่น หน้าเข้าสู่ระบบอาจไม่ใช่ขององค์กรที่แสดงไว้"</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"ดำเนินการต่อผ่านเบราว์เซอร์"</string>
+ <string name="ok" msgid="1509280796718850364">"ตกลง"</string>
+ <string name="page_info" msgid="4048529256302257195">"ข้อมูลหน้าเว็บ"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"ที่อยู่:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"คำเตือนเกี่ยวกับความปลอดภัย"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"ดูใบรับรอง"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"ใบรับรองนี้ไม่ได้มาจากผู้ออกที่เชื่อถือได้"</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"ชื่อไซต์ไม่ตรงกับในใบรับรอง"</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"ใบรับรองนี้หมดอายุแล้ว"</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"ใบรับรองนี้ยังใช้งานไม่ได้"</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"ใบรับรองนี้มีวันที่ไม่ถูกต้อง"</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"ใบรับรองนี้ไม่ถูกต้อง"</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"ข้อผิดพลาดใบรับรองที่ไม่รู้จัก"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-tl/strings.xml b/packages/CaptivePortalLogin/res/values-tl/strings.xml
index 565ef8f486e4..07a247992197 100644
--- a/packages/CaptivePortalLogin/res/values-tl/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-tl/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"May mga isyu sa seguridad ang network kung saan mo sinusubukang sumali."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Halimbawa, maaaring hindi sa organisasyong ipinapakita ang page sa pag-log in."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Magpatuloy pa rin sa pamamagitan ng browser"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Impormasyon ng pahina"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Address:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Babala sa seguridad"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Tingnan ang certificate"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Ang certificate ay hindi mula sa isang pinagkakatiwalaang kinauukulan."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Ang pangalan ng site ay hindi tumutugma sa pangalan sa certificate."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Nag-expire na ang certificate na ito."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Wala pang bisa ang certificate na ito."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Ang certificate ay mayroong di-wastong petsa."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Di-wasto ang certificate na ito."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Hindi kilalang error ng certificate."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-tr/strings.xml b/packages/CaptivePortalLogin/res/values-tr/strings.xml
index 73d2455dcf3a..cdedd3306a01 100644
--- a/packages/CaptivePortalLogin/res/values-tr/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-tr/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Katılmaya çalıştığınız ağda güvenlik sorunları var."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Örneğin, giriş sayfası, gösterilen kuruluşa ait olmayabilir."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Yine de tarayıcıyla devam et"</string>
+ <string name="ok" msgid="1509280796718850364">"Tamam"</string>
+ <string name="page_info" msgid="4048529256302257195">"Sayfa bilgileri"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Adres:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Güvenlik uyarısı"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Sertifikayı görüntüle"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Bu sertifika güvenilir bir yetkiliden değil."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Sitenin adı sertifika üzerindeki adla eşleşmiyor."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Bu sertifikanın süresi dolmuş."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Bu sertifika henüz geçerli değil."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Bu sertifikanın tarihi geçersiz."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Bu sertifika geçersiz."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Bilinmeyen sertifika hatası."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-uk/strings.xml b/packages/CaptivePortalLogin/res/values-uk/strings.xml
index 0e818d3e3ca2..0f4cd1672427 100644
--- a/packages/CaptivePortalLogin/res/values-uk/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-uk/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"У мережі, до якої ви намагаєтеся під’єднатись, є проблеми з безпекою."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Наприклад, сторінка входу може не належати вказаній організації."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Усе одно продовжити у веб-переглядачі"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Інфо про стор."</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Адреса:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Застереж. про небезп."</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Переглянути сертиф."</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Сертифікат видано ненадійним центром сертифікації."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Назва сайту не збігається з назвою в сертифікаті."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Термін дії сертиф. завершився."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Цей сертифікат ще не дійсний."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Цей сертифікат має недійсну дату."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Цей сертифікат недійсний."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Помилка невідомого сертифіката."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-vi/strings.xml b/packages/CaptivePortalLogin/res/values-vi/strings.xml
index e51d2aa6cf9e..9c702b953fd5 100644
--- a/packages/CaptivePortalLogin/res/values-vi/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-vi/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Mạng mà bạn đang cố gắng tham gia có vấn đề về bảo mật."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Ví dụ, trang đăng nhập có thể không thuộc về tổ chức được hiển thị."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Vẫn tiếp tục qua trình duyệt"</string>
+ <string name="ok" msgid="1509280796718850364">"OK"</string>
+ <string name="page_info" msgid="4048529256302257195">"Thông tin trang"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Địa chỉ:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Cảnh báo bảo mật"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Xem chứng chỉ"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Chứng chỉ này không xuất phát từ tổ chức phát hành đáng tin cậy."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Tên của trang web không khớp với tên trên chứng chỉ."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Chứng chỉ này đã hết hạn."</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Chứng chỉ này chưa hợp lệ."</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Chứng chỉ này có ngày không hợp lệ."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Chứng chỉ này không hợp lệ."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Lỗi chứng chỉ không xác định."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml b/packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml
index ce822e7f24bf..70c2a08682af 100644
--- a/packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-zh-rCN/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"您尝试加入的网络存在安全问题。"</string>
<string name="ssl_error_example" msgid="647898534624078900">"例如,登录页面可能并不属于页面上显示的单位。"</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"仍然通过浏览器继续操作"</string>
+ <string name="ok" msgid="1509280796718850364">"确定"</string>
+ <string name="page_info" msgid="4048529256302257195">"网页信息"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"网址:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"安全警告"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"查看证书"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"该证书并非来自可信的授权中心。"</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"网站的名称与证书上的名称不一致。"</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"该证书已过期。"</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"该证书尚未生效。"</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"该证书的日期无效。"</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"该证书无效。"</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"未知证书错误。"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml b/packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml
index 9010e1eebbb6..df1c700582ff 100644
--- a/packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-zh-rHK/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"您正在嘗試加入的網絡有安全性問題。"</string>
<string name="ssl_error_example" msgid="647898534624078900">"例如,登入頁面並不屬於所顯示的機構。"</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"透過瀏覽器繼續"</string>
+ <string name="ok" msgid="1509280796718850364">"確定"</string>
+ <string name="page_info" msgid="4048529256302257195">"網頁資訊"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"地址:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"安全性警告"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"查看憑證"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"這個憑證並非由受信任的權威機構發出。"</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"網站名稱與憑證上的名稱不相符。"</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"這個憑證已過期。"</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"這個憑證尚未生效。"</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"此憑證的日期無效。"</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"此憑證是無效的。"</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"不明的憑證錯誤。"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml b/packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml
index 5b535e2a62cf..2a2e39729f2e 100644
--- a/packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-zh-rTW/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"你嘗試加入的網路有安全問題。"</string>
<string name="ssl_error_example" msgid="647898534624078900">"例如,登入網頁中顯示的機構可能並非該網頁實際隸屬的機構。"</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"透過瀏覽器繼續"</string>
+ <string name="ok" msgid="1509280796718850364">"確定"</string>
+ <string name="page_info" msgid="4048529256302257195">"頁面資訊"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"位址:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"安全性警告"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"檢視憑證"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"這個憑證並非來自信任的授權單位。"</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"網站名稱與憑證上的名稱不相符。"</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"此憑證已過期"</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"這個憑證尚未生效。"</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"這個憑證的日期無效。"</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"這個憑證無效。"</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"不明的憑證錯誤。"</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values-zu/strings.xml b/packages/CaptivePortalLogin/res/values-zu/strings.xml
index 866ba187df16..794364588f94 100644
--- a/packages/CaptivePortalLogin/res/values-zu/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-zu/strings.xml
@@ -9,4 +9,16 @@
<string name="ssl_error_warning" msgid="6653188881418638872">"Inethiwekhi ozama ukuyijoyina inezinkinga zokuvikela."</string>
<string name="ssl_error_example" msgid="647898534624078900">"Isibonelo, ikhasi lokungena ngemvume kungenzeka lingelenhlangano ebonisiwe."</string>
<string name="ssl_error_continue" msgid="6492718244923937110">"Qhubeka noma kunjalo ngesiphequluli"</string>
+ <string name="ok" msgid="1509280796718850364">"KULUNGILE"</string>
+ <string name="page_info" msgid="4048529256302257195">"Ulwazi lekhasi"</string>
+ <string name="page_info_address" msgid="2222306609532903254">"Ikheli:"</string>
+ <string name="ssl_security_warning_title" msgid="6607795404322797541">"Isexwayiso sokuvikeleka"</string>
+ <string name="ssl_error_view_certificate" msgid="1472768887529093862">"Buka isitifiketi"</string>
+ <string name="ssl_error_untrusted" msgid="7754507359360636447">"Lesi sitifiketi asiphumi embusweni othembekile."</string>
+ <string name="ssl_error_mismatch" msgid="3809794439740523641">"Igama lale ngosi alifani negama elikusitifiketi."</string>
+ <string name="ssl_error_expired" msgid="5739349389499575559">"Lesi sitifiketi siphelelwe yisikhathi"</string>
+ <string name="ssl_error_not_yet_valid" msgid="8193083327719048247">"Lesi sitifiketi asilungile okwamanje"</string>
+ <string name="ssl_error_date_invalid" msgid="3705563379257285534">"Lesi sitifiketi sinosuku olungalungile."</string>
+ <string name="ssl_error_invalid" msgid="9041704741505449967">"Lesi sitifiketi asilungile."</string>
+ <string name="ssl_error_unknown" msgid="5679243486524754571">"Iphutha lesitifiketi elingaziwa."</string>
</resources>
diff --git a/packages/CaptivePortalLogin/res/values/strings.xml b/packages/CaptivePortalLogin/res/values/strings.xml
index f486fe4c5ddf..e9698dbbd784 100644
--- a/packages/CaptivePortalLogin/res/values/strings.xml
+++ b/packages/CaptivePortalLogin/res/values/strings.xml
@@ -9,5 +9,17 @@
<string name="ssl_error_warning">The network you&#8217;re trying to join has security issues.</string>
<string name="ssl_error_example">For example, the login page may not belong to the organization shown.</string>
<string name="ssl_error_continue">Continue anyway via browser</string>
+ <string name="ssl_error_untrusted">This certificate isn\'t from a trusted authority.</string>
+ <string name="ssl_error_mismatch">The name of the site doesn\'t match the name on the certificate.</string>
+ <string name="ssl_error_expired">This certificate has expired.</string>
+ <string name="ssl_error_not_yet_valid">This certificate isn\'t valid yet.</string>
+ <string name="ssl_error_date_invalid">This certificate has an invalid date.</string>
+ <string name="ssl_error_invalid">This certificate is invalid.</string>
+ <string name="ssl_error_unknown">Unknown certificate error.</string>
+ <string name="ssl_security_warning_title">Security warning</string>
+ <string name="ssl_error_view_certificate">View certificate</string>
+ <string name="ok">OK</string>
+ <string name="page_info_address">Address:</string>
+ <string name="page_info">Page info</string>
</resources>
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 0ba37aedc8f7..83084c519f19 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -20,8 +20,10 @@ import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_PROBE_SPEC;
import static android.net.captiveportal.CaptivePortalProbeSpec.HTTP_LOCATION_HEADER_NAME;
import android.app.Activity;
+import android.app.AlertDialog;
import android.app.LoadedApk;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.CaptivePortal;
@@ -33,6 +35,7 @@ import android.net.NetworkRequest;
import android.net.Proxy;
import android.net.Uri;
import android.net.captiveportal.CaptivePortalProbeSpec;
+import android.net.http.SslCertificate;
import android.net.http.SslError;
import android.net.wifi.WifiInfo;
import android.os.Build;
@@ -42,8 +45,9 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
-import android.util.TypedValue;
import android.util.SparseArray;
+import android.util.TypedValue;
+import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -52,8 +56,8 @@ import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
-import android.webkit.WebView;
import android.webkit.WebViewClient;
+import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
@@ -276,6 +280,13 @@ public class CaptivePortalLoginActivity extends Activity {
@Override
public void onDestroy() {
super.onDestroy();
+ final WebView webview = (WebView) findViewById(R.id.webview);
+ if (webview != null) {
+ webview.stopLoading();
+ webview.setWebViewClient(null);
+ webview.setWebChromeClient(null);
+ webview.destroy();
+ }
if (mNetworkCallback != null) {
// mNetworkCallback is not null if mUrl is not null.
mCm.unregisterNetworkCallback(mNetworkCallback);
@@ -382,6 +393,7 @@ public class CaptivePortalLoginActivity extends Activity {
private static final String INTERNAL_ASSETS = "file:///android_asset/";
private final String mBrowserBailOutToken = Long.toString(new Random().nextLong());
+ private final String mCertificateOutToken = Long.toString(new Random().nextLong());
// How many Android device-independent-pixels per scaled-pixel
// dp/sp = (px/sp) / (px/dp) = (1/sp) / (1/dp)
private final float mDpPerSp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 1,
@@ -397,6 +409,10 @@ public class CaptivePortalLoginActivity extends Activity {
return mPagesLoaded > 1;
}
+ private String mSslErrorTitle = null;
+ private SslErrorHandler mSslErrorHandler = null;
+ private SslError mSslError = null;
+
@Override
public void onPageStarted(WebView view, String urlString, Bitmap favicon) {
if (urlString.contains(mBrowserBailOutToken)) {
@@ -473,12 +489,16 @@ public class CaptivePortalLoginActivity extends Activity {
logMetricsEvent(MetricsEvent.CAPTIVE_PORTAL_LOGIN_ACTIVITY_SSL_ERROR);
final String sslErrorPage = makeSslErrorPage();
view.loadDataWithBaseURL(INTERNAL_ASSETS, sslErrorPage, "text/HTML", "UTF-8", null);
+ mSslErrorTitle = view.getTitle() == null ? "" : view.getTitle();
+ mSslErrorHandler = handler;
+ mSslError = error;
}
private String makeSslErrorPage() {
final String warningMsg = getString(R.string.ssl_error_warning);
final String exampleMsg = getString(R.string.ssl_error_example);
final String continueMsg = getString(R.string.ssl_error_continue);
+ final String certificateMsg = getString(R.string.ssl_error_view_certificate);
return String.join("\n",
"<html>",
"<head>",
@@ -516,13 +536,18 @@ public class CaptivePortalLoginActivity extends Activity {
" text-decoration:none;",
" text-transform:uppercase;",
" }",
+ " a.certificate {",
+ " margin-top:0px;",
+ " }",
" </style>",
"</head>",
"<body>",
" <p><img src=quantum_ic_warning_amber_96.png><br>",
" <div class=warn>" + warningMsg + "</div>",
" <div class=example>" + exampleMsg + "</div>",
- " <a href=" + mBrowserBailOutToken + ">" + continueMsg + "</a>",
+ " <a href=" + mBrowserBailOutToken + ">" + continueMsg + "</a><br>",
+ " <a class=certificate href=" + mCertificateOutToken + ">" + certificateMsg +
+ "</a>",
"</body>",
"</html>");
}
@@ -533,8 +558,50 @@ public class CaptivePortalLoginActivity extends Activity {
startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(url)));
return true;
}
+ if (url.contains(mCertificateOutToken) && mSslError != null) {
+ showSslAlertDialog(mSslErrorHandler, mSslError, mSslErrorTitle);
+ return true;
+ }
return false;
}
+ private void showSslAlertDialog(SslErrorHandler handler, SslError error, String title) {
+ final LayoutInflater factory = LayoutInflater.from(CaptivePortalLoginActivity.this);
+ final View sslWarningView = factory.inflate(R.layout.ssl_warning, null);
+
+ // Set Security certificate
+ setViewSecurityCertificate(sslWarningView.findViewById(R.id.certificate_layout), error);
+ ((TextView) sslWarningView.findViewById(R.id.ssl_error_type))
+ .setText(sslErrorName(error));
+ ((TextView) sslWarningView.findViewById(R.id.title)).setText(mSslErrorTitle);
+ ((TextView) sslWarningView.findViewById(R.id.address)).setText(error.getUrl());
+
+ AlertDialog sslAlertDialog = new AlertDialog.Builder(CaptivePortalLoginActivity.this)
+ .setTitle(R.string.ssl_security_warning_title)
+ .setView(sslWarningView)
+ .setPositiveButton(R.string.ok, (DialogInterface dialog, int whichButton) -> {
+ // handler.cancel is called via OnCancelListener.
+ dialog.cancel();
+ })
+ .setOnCancelListener((DialogInterface dialogInterface) -> handler.cancel())
+ .create();
+ sslAlertDialog.show();
+ }
+
+ private void setViewSecurityCertificate(LinearLayout certificateLayout, SslError error) {
+ SslCertificate cert = error.getCertificate();
+
+ View certificateView = cert.inflateCertificateView(CaptivePortalLoginActivity.this);
+ final LinearLayout placeholder = (LinearLayout) certificateView
+ .findViewById(com.android.internal.R.id.placeholder);
+ LayoutInflater factory = LayoutInflater.from(CaptivePortalLoginActivity.this);
+
+ TextView textView = (TextView) factory.inflate(
+ R.layout.ssl_error_msg, placeholder, false);
+ textView.setText(sslErrorMessage(error));
+ placeholder.addView(textView);
+
+ certificateLayout.addView(certificateView);
+ }
}
private class MyWebChromeClient extends WebChromeClient {
@@ -587,4 +654,18 @@ public class CaptivePortalLoginActivity extends Activity {
private static String sslErrorName(SslError error) {
return SSL_ERRORS.get(error.getPrimaryError(), "UNKNOWN");
}
+
+ private static final SparseArray<Integer> SSL_ERROR_MSGS = new SparseArray<>();
+ static {
+ SSL_ERROR_MSGS.put(SslError.SSL_NOTYETVALID, R.string.ssl_error_not_yet_valid);
+ SSL_ERROR_MSGS.put(SslError.SSL_EXPIRED, R.string.ssl_error_expired);
+ SSL_ERROR_MSGS.put(SslError.SSL_IDMISMATCH, R.string.ssl_error_mismatch);
+ SSL_ERROR_MSGS.put(SslError.SSL_UNTRUSTED, R.string.ssl_error_untrusted);
+ SSL_ERROR_MSGS.put(SslError.SSL_DATE_INVALID, R.string.ssl_error_date_invalid);
+ SSL_ERROR_MSGS.put(SslError.SSL_INVALID, R.string.ssl_error_invalid);
+ }
+
+ private static Integer sslErrorMessage(SslError error) {
+ return SSL_ERROR_MSGS.get(error.getPrimaryError(), R.string.ssl_error_unknown);
+ }
}
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index 11366848874a..60153fcbc26b 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -78,8 +78,6 @@ import java.util.Map;
public class Assistant extends NotificationAssistantService {
private static final String TAG = "ExtAssistant";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- public static final boolean AUTO_DEMOTE_NOTIFICATIONS = SystemProperties.getBoolean(
- "debug.demote_notifs", false);
public static final boolean AGE_NOTIFICATIONS = SystemProperties.getBoolean(
"debug.age_notifs", false);
@@ -242,7 +240,8 @@ public class Assistant extends NotificationAssistantService {
if (!smartReplies.isEmpty()) {
signals.putCharSequenceArrayList(Adjustment.KEY_SMART_REPLIES, smartReplies);
}
- if (AUTO_DEMOTE_NOTIFICATIONS) {
+ if (Settings.Secure.getInt(getContentResolver(),
+ Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL, 0) == 1) {
if (mNotificationCategorizer.shouldSilence(entry)) {
final int importance = entry.getImportance() < IMPORTANCE_LOW
? entry.getImportance() : IMPORTANCE_LOW;
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 4abcf73af109..c9ee5c87de0f 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -541,14 +541,14 @@ public class ExternalStorageProvider extends FileSystemProvider {
}
@Override
- public Cursor querySearchDocuments(String rootId, String query, String[] projection)
+ public Cursor querySearchDocuments(String rootId, String[] projection, Bundle queryArgs)
throws FileNotFoundException {
final File parent;
synchronized (mRootsLock) {
parent = mRoots.get(rootId).path;
}
- return querySearchDocuments(parent, query, projection, Collections.emptySet());
+ return querySearchDocuments(parent, projection, Collections.emptySet(), queryArgs);
}
@Override
diff --git a/packages/SettingsLib/SettingsSpinner/res/values/styles.xml b/packages/SettingsLib/SettingsSpinner/res/values/styles.xml
index 8447b083b9e1..8af20e20ede9 100644
--- a/packages/SettingsLib/SettingsSpinner/res/values/styles.xml
+++ b/packages/SettingsLib/SettingsSpinner/res/values/styles.xml
@@ -17,7 +17,7 @@
<resources>
<style name="SettingsSpinnerTitleBar">
- <item name="android:textAppearance">?android:attr/textAppearance</item>
+ <item name="android:textAppearance">?android:attr/textAppearanceButton</item>
<item name="android:paddingStart">16dp</item>
<item name="android:paddingEnd">36dp</item>
<item name="android:paddingTop">8dp</item>
diff --git a/packages/SettingsLib/res/drawable/list_divider_dark.xml b/packages/SettingsLib/res/drawable/list_divider_dark.xml
deleted file mode 100644
index 5773d9ef710c..000000000000
--- a/packages/SettingsLib/res/drawable/list_divider_dark.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2017 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-
-<shape
- xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="#64000000" />
- <size
- android:height="1dp"
- android:width="1dp" />
-</shape>
diff --git a/packages/SettingsLib/res/layout/preference_two_target_divider.xml b/packages/SettingsLib/res/layout/preference_two_target_divider.xml
index 60efed41870c..b81dd83d2586 100644
--- a/packages/SettingsLib/res/layout/preference_two_target_divider.xml
+++ b/packages/SettingsLib/res/layout/preference_two_target_divider.xml
@@ -27,5 +27,5 @@
<View
android:layout_width="1dp"
android:layout_height="match_parent"
- android:background="@drawable/list_divider_dark" />
+ android:background="?android:attr/listDivider" />
</LinearLayout> \ No newline at end of file
diff --git a/packages/SettingsLib/res/values/colors.xml b/packages/SettingsLib/res/values/colors.xml
index 02b7ea6ef7a8..66bbb3a6c890 100644
--- a/packages/SettingsLib/res/values/colors.xml
+++ b/packages/SettingsLib/res/values/colors.xml
@@ -18,4 +18,5 @@
<color name="disabled_text_color">#66000000</color> <!-- 38% black -->
<color name="usage_graph_dots">@*android:color/tertiary_device_default_settings</color>
+ <color name="list_divider_color">#64000000</color>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 0dbc037f2298..2f082b959e68 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -152,7 +152,11 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
private boolean mNetworkScoringUiEnabled;
private long mMaxSpeedLabelScoreCacheAge;
-
+ private static final String WIFI_SECURITY_PSK = "PSK";
+ private static final String WIFI_SECURITY_EAP = "EAP";
+ private static final String WIFI_SECURITY_SAE = "SAE";
+ private static final String WIFI_SECURITY_OWE = "OWE";
+ private static final String WIFI_SECURITY_SUITE_B_192 = "SUITE_B_192";
@VisibleForTesting
Scanner mScanner;
@@ -505,13 +509,18 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
* {@link #updateAccessPoints(List, List)}.
*/
private void fetchScansAndConfigsAndUpdateAccessPoints() {
- final List<ScanResult> newScanResults = mWifiManager.getScanResults();
+ List<ScanResult> newScanResults = mWifiManager.getScanResults();
+
+ // Filter all unsupported networks from the scan result list
+ final List<ScanResult> filteredScanResults =
+ filterScanResultsByCapabilities(newScanResults);
+
if (isVerboseLoggingEnabled()) {
- Log.i(TAG, "Fetched scan results: " + newScanResults);
+ Log.i(TAG, "Fetched scan results: " + filteredScanResults);
}
List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
- updateAccessPoints(newScanResults, configs);
+ updateAccessPoints(filteredScanResults, configs);
}
/** Update the internal list of access points. */
@@ -937,4 +946,49 @@ public class WifiTracker implements LifecycleObserver, OnStart, OnStop, OnDestro
mListener.onAccessPointsChanged();
}
+
+ /**
+ * Filters unsupported networks from scan results. New WPA3 networks and OWE networks
+ * may not be compatible with the device HW/SW.
+ * @param scanResults List of scan results
+ * @return List of filtered scan results based on local device capabilities
+ */
+ private List<ScanResult> filterScanResultsByCapabilities(List<ScanResult> scanResults) {
+ if (scanResults == null) {
+ return null;
+ }
+
+ // Get and cache advanced capabilities
+ final boolean isOweSupported = mWifiManager.isOweSupported();
+ final boolean isSaeSupported = mWifiManager.isWpa3SaeSupported();
+ final boolean isSuiteBSupported = mWifiManager.isWpa3SuiteBSupported();
+
+ List<ScanResult> filteredScanResultList = new ArrayList<>();
+
+ // Iterate through the list of scan results and filter out APs which are not
+ // compatible with our device.
+ for (ScanResult scanResult : scanResults) {
+ if (scanResult.capabilities.contains(WIFI_SECURITY_PSK)) {
+ // All devices (today) support RSN-PSK or WPA-PSK
+ // Add this here because some APs may support both PSK and SAE and the check
+ // below will filter it out.
+ filteredScanResultList.add(scanResult);
+ continue;
+ }
+
+ if ((scanResult.capabilities.contains(WIFI_SECURITY_SUITE_B_192) && !isSuiteBSupported)
+ || (scanResult.capabilities.contains(WIFI_SECURITY_SAE) && !isSaeSupported)
+ || (scanResult.capabilities.contains(WIFI_SECURITY_OWE) && !isOweSupported)) {
+ if (isVerboseLoggingEnabled()) {
+ Log.v(TAG, "filterScanResultsByCapabilities: Filtering SSID "
+ + scanResult.SSID + " with capabilities: " + scanResult.capabilities);
+ }
+ } else {
+ // Safe to add
+ filteredScanResultList.add(scanResult);
+ }
+ }
+
+ return filteredScanResultList;
+ }
}
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
index b51ad1cb4922..51f6a4b92413 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
@@ -20,8 +20,8 @@
<!-- This is a view that shows general status information in Keyguard. -->
<com.android.keyguard.KeyguardSliceView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="16dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
diff --git a/packages/SystemUI/res/drawable/ic_notification_block.xml b/packages/SystemUI/res/drawable/ic_notification_block.xml
new file mode 100644
index 000000000000..572e97b6badc
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_notification_block.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M12.0,2.0C6.48,2.0 2.0,6.48 2.0,12.0s4.48,10.0 10.0,10.0 10.0,-4.48 10.0,-10.0S17.52,2.0 12.0,2.0zM4.0,12.0c0.0,-4.42 3.58,-8.0 8.0,-8.0 1.85,0.0 3.5,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4.0,13.85 4.0,12.0zm8.0,8.0c-1.85,0.0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20.0,10.15 20.0,12.0c0.0,4.42 -3.58,8.0 -8.0,8.0z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_notifications_alert.xml b/packages/SystemUI/res/drawable/ic_notifications_alert.xml
new file mode 100644
index 000000000000..eb7b8eeb9251
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_notifications_alert.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M7.58 4.08L6.15 2.65C3.75 4.48 2.17 7.3 2.03 10.5h2c.15-2.65 1.51-4.97 3.55-6.42zm12.39 6.42h2c-.15-3.2-1.73-6.02-4.12-7.85l-1.42 1.43c2.02 1.45 3.39 3.77 3.54 6.42zM18 11c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2v-5zm-6 11c.14 0 .27-.01.4-.04.65-.14 1.18-.58 1.44-1.18.1-.24.15-.5.15-.78h-4c.01 1.1.9 2 2.01 2z"
+ android:fillColor="#FF000000"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_notifications_silence.xml b/packages/SystemUI/res/drawable/ic_notifications_silence.xml
new file mode 100644
index 000000000000..ff136eb44aac
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_notifications_silence.xml
@@ -0,0 +1,28 @@
+<!--
+Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M0 0h24v24H0z"
+ />
+ <path
+ android:pathData="M20 18.69L7.84 6.14 5.27 3.49 4 4.76l2.8 2.8v.01c-.52.99-.8 2.16-.8 3.42v5l-2 2v1h13.73l2 2L21 19.72l-1-1.03zM12 22c1.11 0 2-.89 2-2h-4c0 1.11.89 2 2 2zm6-7.32V11c0-3.08-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68c-.15.03-.29.08-.42.12-.1.03-.2.07-.3.11h-.01c-.01 0-.01 0-.02.01-.23.09-.46.2-.68.31 0 0-.01 0-.01.01L18 14.68z"
+ android:fillColor="#FF000000"
+ />
+</vector>
diff --git a/packages/SystemUI/res/drawable/privacy_chip_bg.xml b/packages/SystemUI/res/drawable/privacy_chip_bg.xml
index 8247c27ff850..36d06591460b 100644
--- a/packages/SystemUI/res/drawable/privacy_chip_bg.xml
+++ b/packages/SystemUI/res/drawable/privacy_chip_bg.xml
@@ -16,7 +16,7 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="#bbbbbb" />
+ <solid android:color="#4a4a4a" />
<padding android:padding="@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/drawable/stat_sys_camera.xml b/packages/SystemUI/res/drawable/stat_sys_camera.xml
new file mode 100644
index 000000000000..eb3e9632dd35
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_camera.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetLeft="3dp"
+ android:insetRight="3dp">
+ <vector
+ android:width="17dp"
+ android:height="17dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFF"
+ android:pathData="M20,5h-3.17L15,3H9L7.17,5H4C2.9,5 2,5.9 2,7v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V7C22,5.9 21.1,5 20,5zM20,19H4V7h16V19zM12,9c-2.21,0 -4,1.79 -4,4c0,2.21 1.79,4 4,4s4,-1.79 4,-4C16,10.79 14.21,9 12,9z"/>
+ </vector>
+</inset>
diff --git a/packages/SystemUI/res/drawable/stat_sys_mic_none.xml b/packages/SystemUI/res/drawable/stat_sys_mic_none.xml
new file mode 100644
index 000000000000..d6bdf9fbaa78
--- /dev/null
+++ b/packages/SystemUI/res/drawable/stat_sys_mic_none.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="18dp"
+ android:height="18dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFF"
+ android:pathData="M12,14c1.66,0 3,-1.34 3,-3V5c0,-1.66 -1.34,-3 -3,-3S9,3.34 9,5v6C9,12.66 10.34,14 12,14zM11,5c0,-0.55 0.45,-1 1,-1s1,0.45 1,1v6c0,0.55 -0.45,1 -1,1s-1,-0.45 -1,-1V5z"/>
+ <path
+ android:fillColor="#FFF"
+ android:pathData="M17,11c0,2.76 -2.24,5 -5,5s-5,-2.24 -5,-5H5c0,3.53 2.61,6.43 6,6.92V21h2v-3.08c3.39,-0.49 6,-3.39 6,-6.92H17z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
index ddefb6a43a6f..cbdd51b24388 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
@@ -18,11 +18,14 @@
<com.android.systemui.privacy.OngoingPrivacyChip
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/privacy_chip"
- android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_margin="@dimen/ongoing_appops_chip_margin"
+ 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|end"
+ android:layout_gravity="center_vertical|start"
android:orientation="horizontal"
android:paddingStart="@dimen/ongoing_appops_chip_side_padding"
android:paddingEnd="@dimen/ongoing_appops_chip_side_padding"
@@ -38,12 +41,17 @@
/>
<TextView
- android:id="@+id/app_name"
+ 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"
+ android:layout_marginEnd="@dimen/ongoing_appops_chip_icon_margin"
/>
</com.android.systemui.privacy.OngoingPrivacyChip> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_dialog_content.xml b/packages/SystemUI/res/layout/ongoing_privacy_dialog_content.xml
index b5e24a04f85e..2f7d486a1372 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_dialog_content.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_dialog_content.xml
@@ -29,22 +29,30 @@
android:orientation="vertical"
android:padding="@dimen/ongoing_appops_dialog_content_padding">
- <LinearLayout
- android:id="@+id/icons_container"
+ <TextView
+ android:id="@+id/title"
android:layout_width="match_parent"
- android:layout_height="@dimen/ongoing_appops_dialog_icon_height"
- android:orientation="horizontal"
+ android:layout_height="wrap_content"
android:gravity="center"
- android:importantForAccessibility="no"
+ android:textDirection="locale"
+ android:textAppearance="@style/TextAppearance.AppOpsDialog.Title"
+ android:textColor="@*android:color/text_color_primary"
+ android:paddingStart="@dimen/ongoing_appops_dialog_title_padding"
+ android:paddingEnd="@dimen/ongoing_appops_dialog_title_padding"
+ android:paddingBottom="@dimen/ongoing_appops_dialog_sep"
/>
<LinearLayout
- android:id="@+id/text_container"
+ android:id="@+id/items_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="start"
/>
+
+ <include android:id="@+id/overflow" layout="@layout/ongoing_privacy_dialog_item"
+ android:visibility="gone" />
+
</LinearLayout>
</ScrollView> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_dialog_item.xml b/packages/SystemUI/res/layout/ongoing_privacy_dialog_item.xml
new file mode 100644
index 000000000000..f05f7bad36ba
--- /dev/null
+++ b/packages/SystemUI/res/layout/ongoing_privacy_dialog_item.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:fillViewport="true"
+ android:orientation="horizontal"
+ android:layout_marginTop="@dimen/ongoing_appops_dialog_text_margin"
+ android:focusable="true" >
+
+ <ImageView
+ android:id="@+id/app_icon"
+ android:layout_height="@dimen/ongoing_appops_dialog_icon_height"
+ android:layout_width="@dimen/ongoing_appops_dialog_icon_height"
+ />
+
+ <TextView
+ android:id="@+id/app_name"
+ android:layout_height="@dimen/ongoing_appops_dialog_icon_height"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:gravity="bottom|start"
+ android:textDirection="locale"
+ android:textAppearance="@style/TextAppearance.AppOpsDialog.Item"
+ android:textColor="@*android:color/text_color_primary"
+ android:paddingStart="@dimen/ongoing_appops_dialog_text_padding"
+ android:paddingEnd="@dimen/ongoing_appops_dialog_text_padding"
+
+ />
+
+ <LinearLayout
+ android:id="@+id/icons"
+ android:layout_height="@dimen/ongoing_appops_dialog_icon_height"
+ android:layout_width="wrap_content"
+ android:gravity="end"
+ android:visibility="gone"
+ />
+</LinearLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index f554150ab0d0..890bf5d8ac45 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -62,7 +62,7 @@
android:layout_weight="1"
android:layout_marginEnd="32dp"
android:ellipsize="marquee"
- android:textAppearance="@style/TextAppearance.QS.TileLabel"
+ android:textAppearance="@style/TextAppearance.QS.CarrierInfo"
android:textColor="?android:attr/textColorPrimary"
android:textDirection="locale"
android:singleLine="true" />
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index 980442c488f4..f34161e285da 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -79,7 +79,7 @@
android:padding="0dp"
android:visibility="gone"
android:gravity="center"
- android:textAppearance="@style/TextAppearance.QS.TileLabel"
+ android:textAppearance="@style/TextAppearance.QS.TileLabel.Secondary"
android:textColor="?android:attr/textColorSecondary"/>
<View
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
index e7f2c51d124b..22b8d2ff4db0 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml
@@ -59,7 +59,7 @@
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="horizontal"
- android:gravity="center_vertical|end">
+ android:gravity="center_vertical|end" >
<include layout="@layout/ongoing_privacy_chip" />
@@ -67,6 +67,7 @@
android:id="@+id/battery"
android:layout_height="match_parent"
android:layout_width="wrap_content"
- android:gravity="center_vertical|end" />
+ android:gravity="center_vertical|end"
+ android:layout_gravity="center_vertical|end" />
</LinearLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index bb0c6f6acb06..df858f0c54e2 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -34,4 +34,5 @@
<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 0e41a7fd7d28..97f5f8672b7d 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -369,6 +369,7 @@
<dimen name="qs_page_indicator_height">8dp</dimen>
<dimen name="qs_tile_icon_size">24dp</dimen>
<dimen name="qs_tile_text_size">12sp</dimen>
+ <dimen name="qs_carrier_info_text_size">14sp</dimen>
<dimen name="qs_tile_divider_height">1dp</dimen>
<dimen name="qs_panel_padding">16dp</dimen>
<dimen name="qs_dual_tile_height">112dp</dimen>
@@ -939,18 +940,34 @@
that just start below the notch. -->
<dimen name="display_cutout_touchable_region_size">12dp</dimen>
+ <!-- Padding below Ongoing App Ops dialog title -->
+ <dimen name="ongoing_appops_dialog_sep">16dp</dimen>
+ <!--Padding around text items in Ongoing App Ops dialog -->
+ <dimen name="ongoing_appops_dialog_text_padding">16dp</dimen>
<!-- Height of icons in Ongoing App Ops dialog. Both App Op icon and application icon -->
- <dimen name="ongoing_appops_dialog_icon_height">48dp</dimen>
+ <dimen name="ongoing_appops_dialog_icon_height">28dp</dimen>
<!-- Margin between text lines in Ongoing App Ops dialog -->
<dimen name="ongoing_appops_dialog_text_margin">15dp</dimen>
+ <!-- Side padding of title in Ongoing App Ops dialog -->
+ <dimen name="ongoing_appops_dialog_title_padding">10dp</dimen>
<!-- Padding around Ongoing App Ops dialog content -->
<dimen name="ongoing_appops_dialog_content_padding">24dp</dimen>
- <!-- Margins around the Ongoing App Ops chip. In landscape, the side margins are 0 -->
+ <!-- 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>
<!-- Start and End padding for Ongoing App Ops chip -->
<dimen name="ongoing_appops_chip_side_padding">6dp</dimen>
<!-- Padding between background of Ongoing App Ops chip and content -->
- <dimen name="ongoing_appops_chip_bg_padding">4dp</dimen>
+ <dimen name="ongoing_appops_chip_bg_padding">0dp</dimen>
+ <!-- Margin between icons of Ongoing App Ops chip -->
+ <dimen name="ongoing_appops_chip_icon_margin">4dp</dimen>
+ <!-- Icon size of Ongoing App Ops chip -->
+ <dimen name="ongoing_appops_chip_icon_size">18dp</dimen>
<!-- Radius of Ongoing App Ops chip corners -->
<dimen name="ongoing_appops_chip_bg_corner_radius">12dp</dimen>
+ <!-- Text size for Ongoing App Ops dialog title -->
+ <dimen name="ongoing_appops_dialog_title_size">24sp</dimen>
+ <!-- Text size for Ongoing App Ops dialog items -->
+ <dimen name="ongoing_appops_dialog_item_size">20sp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 50454fc9bcf2..4a0bc9b81378 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2250,39 +2250,48 @@
app for debugging. Will not be seen by users. [CHAR LIMIT=20] -->
<string name="heap_dump_tile_name">Dump SysUI Heap</string>
+ <!-- Text on chip for multiple apps using a single app op [CHAR LIMIT=10] -->
+ <string name="ongoing_privacy_chip_multiple_apps"><xliff:g id="num_apps" example="3">%d</xliff:g> apps</string>
+
<!-- Content description for ongoing privacy chip. Use with a single app [CHAR LIMIT=NONE]-->
<string name="ongoing_privacy_chip_content_single_app"><xliff:g id="app" example="Example App">%1$s</xliff:g> is using your <xliff:g id="types_list" example="camera, location">%2$s</xliff:g>.</string>
<!-- Content description for ongoing privacy chip. Use with multiple apps [CHAR LIMIT=NONE]-->
<string name="ongoing_privacy_chip_content_multiple_apps">Applications are using your <xliff:g id="types_list" example="camera, location">%s</xliff:g>.</string>
- <!-- Action on Ongoing Privacy Dialog to open application [CHAR LIMIT=10]-->
- <string name="ongoing_privacy_dialog_open_app">Open app</string>
+ <!-- Content description for ongoing privacy chip. Use with multiple apps using same app op[CHAR LIMIT=NONE]-->
+ <string name="ongoing_privacy_chip_content_multiple_apps_single_op"><xliff:g id="num_apps" example="3">%1$d</xliff:g> applications are using your <xliff:g id="type" example="camera">%2$s</xliff:g>.</string>
<!-- Action on Ongoing Privacy Dialog to dismiss [CHAR LIMIT=10]-->
<string name="ongoing_privacy_dialog_cancel">Cancel</string>
- <!-- Action on Ongoing Privacy Dialog to dismiss [CHAR LIMIT=10]-->
- <string name="ongoing_privacy_dialog_okay">Okay</string>
+ <!-- Action on Ongoing Privacy Dialog to open privacy hub [CHAR LIMIT=15]-->
+ <string name="ongoing_privacy_dialog_open_settings">View details</string>
- <!-- Action on Ongoing Privacy Dialog to open privacy hub [CHAR LIMIT=10]-->
- <string name="ongoing_privacy_dialog_open_settings">Settings</string>
+ <!-- Text for item in Ongoing Privacy Dialog title when only one app is using app ops [CHAR LIMIT=NONE] -->
+ <string name="ongoing_privacy_dialog_single_app_title">App using your <xliff:g id="types_list" example="camera( and location)">%s</xliff:g></string>
- <!-- Text for item in Ongoing Privacy Dialog when only one app is using a particular type of app op [CHAR LIMIT=NONE] -->
- <string name="ongoing_privacy_dialog_app_item"><xliff:g id="app" example="Example App">%1$s</xliff:g> is using your <xliff:g id="type" example="camera">%2$s</xliff:g> for the last <xliff:g id="time" example="3">%3$d</xliff:g> min</string>
+ <!-- Text for item in Ongoing Privacy Dialog title when multiple apps is using app ops [CHAR LIMIT=NONE] -->
+ <string name="ongoing_privacy_dialog_multiple_apps_title">Apps using your <xliff:g id="types_list" example="camera( and location)">%s</xliff:g></string>
- <!-- Text for item in Ongoing Privacy Dialog when only multiple apps are using a particular type of app op [CHAR LIMIT=NONE] -->
- <string name="ongoing_privacy_dialog_apps_item"><xliff:g id="apps" example="Camera, Phone">%1$s</xliff:g> are using your <xliff:g id="type" example="camera">%2$s</xliff:g></string>
+ <!-- Separator for types. Include spaces before and after if needed [CHAR LIMIT=10] -->
+ <string name="ongoing_privacy_dialog_separator">,\u0020</string>
- <!-- Text for Ongoing Privacy Dialog when a single app is using app ops [CHAR LIMIT=NONE] -->
- <string name="ongoing_privacy_dialog_single_app"><xliff:g id="app" example="Example App">%1$s</xliff:g> is using your <xliff:g id="types_list" example="camera, location">%2$s</xliff:g></string>
+ <!-- Separator for types, before last type. Include spaces before and after if needed [CHAR LIMIT=10] -->
+ <string name="ongoing_privacy_dialog_last_separator">\u0020and\u0020</string>
- <!-- Text for camera app op [CHAR LIMIT=12]-->
+ <!-- Text for camera app op [CHAR LIMIT=20]-->
<string name="privacy_type_camera">camera</string>
- <!-- Text for location app op [CHAR LIMIT=12]-->
+ <!-- Text for location app op [CHAR LIMIT=20]-->
<string name="privacy_type_location">location</string>
- <!-- Text for microphone app op [CHAR LIMIT=12]-->
+ <!-- Text for microphone app op [CHAR LIMIT=20]-->
<string name="privacy_type_microphone">microphone</string>
+
+ <!-- Text for indicating extra apps using app ops [CHAR LIMIT=NONE] -->
+ <plurals name="ongoing_privacy_dialog_overflow_text">
+ <item quantity="one"><xliff:g id="num_apps" example="1">%d</xliff:g> other app</item>
+ <item quantity="other"><xliff:g id="num_apps" example="3">%d</xliff:g> other app</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 6244e1c4a509..e9aa1b65f48a 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -125,7 +125,7 @@
<style name="TextAppearance.StatusBar.Clock" parent="@*android:style/TextAppearance.StatusBar.Icon">
<item name="android:textSize">@dimen/status_bar_clock_size</item>
- <item name="android:fontFamily">sans-serif-medium</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
<item name="android:textColor">@color/status_bar_clock_color</item>
</style>
@@ -135,7 +135,7 @@
<style name="TextAppearance.StatusBar.Expanded.Clock">
<item name="android:textSize">@dimen/qs_time_expanded_size</item>
- <item name="android:fontFamily">sans-serif-medium</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:textStyle">normal</item>
</style>
@@ -240,9 +240,31 @@
<style name="TextAppearance.QS.TileLabel">
<item name="android:textSize">@dimen/qs_tile_text_size</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+ </style>
+
+ <style name="TextAppearance.QS.TileLabel.Secondary">
+ <item name="android:textSize">@dimen/qs_tile_text_size</item>
<item name="android:fontFamily">sans-serif</item>
</style>
+ <style name="TextAppearance.QS.CarrierInfo">
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+ <item name="android:textSize">@dimen/qs_carrier_info_text_size</item>
+ </style>
+
+ <style name="TextAppearance.AppOpsDialog" />
+
+ <style name="TextAppearance.AppOpsDialog.Title">
+ <item name="android:textSize">@dimen/ongoing_appops_dialog_title_size</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamilyMedium</item>
+ </style>
+
+ <style name="TextAppearance.AppOpsDialog.Item">
+ <item name="android:textSize">@dimen/ongoing_appops_dialog_item_size</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+ </style>
+
<style name="BaseBrightnessDialogContainer" parent="@style/Theme.SystemUI">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierText.java b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
index a0a36878634a..b7d51978fab2 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierText.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierText.java
@@ -16,10 +16,6 @@
package com.android.keyguard;
-import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
-
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -28,6 +24,7 @@ import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
+import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.method.SingleLineTransformationMethod;
import android.util.AttributeSet;
@@ -40,7 +37,9 @@ import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.telephony.TelephonyIntents;
import com.android.settingslib.WirelessUtils;
-import android.telephony.TelephonyManager;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
public class CarrierText extends TextView {
private static final boolean DEBUG = KeyguardConstants.DEBUG;
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
index ac8f0246a608..210b82d1d69c 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
@@ -16,7 +16,6 @@
package com.android.keyguard;
-import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.content.Context;
@@ -37,8 +36,8 @@ import android.widget.Button;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.telephony.IccCardConstants.State;
-import com.android.internal.widget.LockPatternUtils;
import com.android.internal.util.EmergencyAffordanceManager;
+import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.util.EmergencyDialerConstants;
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
index 63b7ae2d856a..c2bbfbf73bb6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java
@@ -22,19 +22,15 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.os.Handler;
-import android.os.HandlerThread;
import android.os.UserHandle;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.euicc.EuiccManager;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
-import android.telephony.SubscriptionManager;
-import android.telephony.SubscriptionInfo;
-import android.telephony.euicc.EuiccManager;
-import android.util.Log;
-
-import java.lang.ref.WeakReference;
/***
* This button is used by the device with embedded SIM card to disable current carrier to unlock
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
index 34df15f17869..cf22286c1614 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java
@@ -19,8 +19,8 @@ package com.android.keyguard;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
-import android.content.res.Resources;
import android.content.res.ColorStateList;
+import android.content.res.Resources;
import android.graphics.Canvas;
import android.media.AudioManager;
import android.os.SystemClock;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index f400f6039882..3cc18ddf3b2a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -23,8 +23,6 @@ import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
-import com.android.internal.annotations.VisibleForTesting;
-
/**
* A Pin based Keyguard input view
*/
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index b8df3c067969..7af27f2ed49a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -21,7 +21,6 @@ import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.res.ColorStateList;
import android.os.UserHandle;
-import androidx.annotation.VisibleForTesting;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
@@ -31,6 +30,8 @@ import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
+import androidx.annotation.VisibleForTesting;
+
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
index 1a09364f564c..272b3bdf56a4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
@@ -15,9 +15,10 @@
*/
package com.android.keyguard;
-import com.android.internal.widget.LockPatternUtils;
import android.content.res.ColorStateList;
+import com.android.internal.widget.LockPatternUtils;
+
public interface KeyguardSecurityView {
static public final int SCREEN_ON = 1;
static public final int VIEW_REVEALED = 2;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index 74e2a6835b41..e6a02506b4a3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -18,8 +18,8 @@ package com.android.keyguard;
import android.annotation.NonNull;
import android.content.Context;
-import android.content.res.TypedArray;
import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
@@ -28,18 +28,15 @@ import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewHierarchyEncoder;
-import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ViewFlipper;
import com.android.internal.widget.LockPatternUtils;
-import java.lang.Override;
-
/**
* Subclass of the current view flipper that allows us to overload dispatchTouchEvent() so
- * we can emulate {@link WindowManager.LayoutParams#FLAG_SLIPPERY} within a view hierarchy.
- *
+ * we can emulate {@link android.view.WindowManager.LayoutParams#FLAG_SLIPPERY} within a view
+ * hierarchy.
*/
public class KeyguardSecurityViewFlipper extends ViewFlipper implements KeyguardSecurityView {
private static final String TAG = "KeyguardSecurityViewFlipper";
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 42c7a5680d11..6528d8c07a6c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -16,32 +16,31 @@
package com.android.keyguard;
-import com.android.internal.telephony.ITelephony;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.IccCardConstants.State;
-import com.android.internal.telephony.PhoneConstants;
-
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.Configuration;
-import android.content.res.Resources;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Color;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import android.telephony.euicc.EuiccManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
+import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.IccCardConstants.State;
+import com.android.internal.telephony.PhoneConstants;
+
/**
* Displays a PIN pad for unlocking.
*/
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index 1b61568276ce..1157f86872ec 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -16,20 +16,19 @@
package com.android.keyguard;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.Resources;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
import android.graphics.Color;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import android.telephony.euicc.EuiccManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@@ -38,8 +37,8 @@ import android.widget.ImageView;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.IccCardConstants.State;
+import com.android.internal.telephony.PhoneConstants;
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index 79966f78373c..c41ef0ede89e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -243,46 +243,6 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe
}
}
- /**
- * Breaks a string in 2 lines where both have similar character count
- * but first line is always longer.
- *
- * @param charSequence Original text.
- * @return Optimal string.
- */
- private static CharSequence findBestLineBreak(CharSequence charSequence) {
- if (TextUtils.isEmpty(charSequence)) {
- return charSequence;
- }
-
- String source = charSequence.toString();
- // Ignore if there is only 1 word,
- // or if line breaks were manually set.
- if (source.contains("\n") || !source.contains(" ")) {
- return source;
- }
-
- final String[] words = source.split(" ");
- final StringBuilder optimalString = new StringBuilder(source.length());
- int current = 0;
- while (optimalString.length() < source.length() - optimalString.length()) {
- optimalString.append(words[current]);
- if (current < words.length - 1) {
- optimalString.append(" ");
- }
- current++;
- }
- optimalString.append("\n");
- for (int i = current; i < words.length; i++) {
- optimalString.append(words[i]);
- if (current < words.length - 1) {
- optimalString.append(" ");
- }
- }
-
- return optimalString.toString();
- }
-
public void setDarkAmount(float darkAmount) {
mDarkAmount = darkAmount;
mRow.setDarkAmount(darkAmount);
diff --git a/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java b/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
index bbc8ecdcc066..5ed9eaad0a00 100644
--- a/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/AutoReinflateContainer.java
@@ -18,7 +18,6 @@ import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
-import android.os.LocaleList;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
diff --git a/packages/SystemUI/src/com/android/systemui/DejankUtils.java b/packages/SystemUI/src/com/android/systemui/DejankUtils.java
index 4ee3bd37ce3c..bec8820a3053 100644
--- a/packages/SystemUI/src/com/android/systemui/DejankUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/DejankUtils.java
@@ -16,12 +16,12 @@
package com.android.systemui;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.util.Assert;
-
import android.os.Handler;
import android.view.Choreographer;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.util.Assert;
+
import java.util.ArrayList;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java b/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java
index 81e4db3b2561..5c0df179dd27 100644
--- a/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java
+++ b/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java
@@ -14,7 +14,6 @@
package com.android.systemui;
-import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.IDockedStackListener;
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index f5ad7476a156..ecf4c0a86bfc 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -32,9 +32,9 @@ import android.view.View;
import android.view.ViewConfiguration;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
-import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.policy.ScrollAdapter;
public class ExpandHelper implements Gefingerpoken {
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
index 1fa925e5ad1f..bab472c2e687 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
@@ -23,7 +23,6 @@ import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
-import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.messages.nano.SystemMessageProto;
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java b/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
index 9d286cf7e6d5..cb9523fcaed1 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
@@ -42,8 +42,6 @@ import com.android.internal.app.AlertController;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
-import com.android.systemui.R;
-
import java.util.ArrayList;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index b1463a3c53ea..16e869e9d317 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -14,6 +14,10 @@
package com.android.systemui;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -33,10 +37,6 @@ import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
import com.android.systemui.util.leak.RotationUtils;
-import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
-import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
-import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
-
public class HardwareUiLayout extends LinearLayout implements Tunable {
private static final String EDGE_BLEED = "sysui_hwui_edge_bleed";
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index d8eb96504e79..1d2d7fafe800 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -20,6 +20,7 @@ import android.app.WallpaperManager;
import android.content.ComponentCallbacks2;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region.Op;
@@ -30,7 +31,6 @@ import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.Display;
import android.view.DisplayInfo;
-import android.graphics.RecordingCanvas;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.WindowManager;
diff --git a/packages/SystemUI/src/com/android/systemui/LatencyTester.java b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
index 1e458fa5c112..50f1b44b05b1 100644
--- a/packages/SystemUI/src/com/android/systemui/LatencyTester.java
+++ b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
@@ -16,17 +16,17 @@
package com.android.systemui;
-import android.hardware.biometrics.BiometricSourceType;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.hardware.biometrics.BiometricSourceType;
import android.os.Build;
import android.os.PowerManager;
import android.os.SystemClock;
-import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.internal.util.LatencyTracker;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.StatusBar;
diff --git a/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java b/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
index f6ad62616a96..f9617cad848e 100644
--- a/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
@@ -21,8 +21,8 @@ import android.util.Log;
import android.view.View;
import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.plugins.ViewProvider;
+import com.android.systemui.shared.plugins.PluginManager;
/**
* Define an interface or abstract class as follows that includes the
diff --git a/packages/SystemUI/src/com/android/systemui/RegionInterceptingFrameLayout.java b/packages/SystemUI/src/com/android/systemui/RegionInterceptingFrameLayout.java
index 6dc2d67a1c78..8351bbfaa430 100644
--- a/packages/SystemUI/src/com/android/systemui/RegionInterceptingFrameLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/RegionInterceptingFrameLayout.java
@@ -21,7 +21,6 @@ import android.graphics.Region;
import android.graphics.Region.Op;
import android.util.AttributeSet;
import android.view.View;
-import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.InternalInsetsInfo;
import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
import android.widget.FrameLayout;
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index c84449683c1c..1dd231ca7642 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -63,6 +63,8 @@ import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
+import androidx.annotation.VisibleForTesting;
+
import com.android.internal.util.Preconditions;
import com.android.systemui.RegionInterceptingFrameLayout.RegionInterceptableView;
import com.android.systemui.fragments.FragmentHostManager;
@@ -79,8 +81,6 @@ import com.android.systemui.util.leak.RotationUtils;
import java.util.ArrayList;
import java.util.List;
-import androidx.annotation.VisibleForTesting;
-
/**
* An overlay that draws screen decorations in software (e.g for rounded corners or display cutout)
* for antialiasing and emulation purposes.
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index e3584cf7493e..36664004a4a6 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -88,8 +88,6 @@ public class SwipeHelper implements Gefingerpoken {
private Runnable mWatchLongPress;
private final long mLongPressTimeout;
- protected boolean mSwipingInProgress;
-
final private int[] mTmpPos = new int[2];
private final int mFalsingThreshold;
private boolean mTouchAboveFalsingThreshold;
@@ -130,10 +128,6 @@ public class SwipeHelper implements Gefingerpoken {
mDisableHwLayers = disableHwLayers;
}
- public boolean isSwipingInProgress() {
- return mSwipingInProgress;
- }
-
private float getPos(MotionEvent ev) {
return mSwipeDirection == X ? ev.getX() : ev.getY();
}
@@ -325,7 +319,6 @@ public class SwipeHelper implements Gefingerpoken {
if (Math.abs(delta) > mPagingTouchSlop
&& Math.abs(delta) > Math.abs(deltaPerpendicular)) {
if (mCallback.canChildBeDragged(mCurrView)) {
- mSwipingInProgress = true;
mCallback.onBeginDrag(mCurrView);
mDragging = true;
mInitialTouchPos = getPos(ev);
@@ -445,7 +438,6 @@ public class SwipeHelper implements Gefingerpoken {
wasRemoved = row.isRemoved();
}
if (!mCancelled || wasRemoved) {
- mSwipingInProgress = false;
mCallback.onChildDismissed(animView);
}
if (endAction != null) {
@@ -637,7 +629,6 @@ public class SwipeHelper implements Gefingerpoken {
!swipedFastEnough() /* useAccelerateInterpolator */);
} else {
// snappity
- mSwipingInProgress = false;
mCallback.onDragCancelled(mCurrView);
snapChild(mCurrView, 0 /* leftTarget */, velocity);
}
diff --git a/packages/SystemUI/src/com/android/systemui/SysUIToast.java b/packages/SystemUI/src/com/android/systemui/SysUIToast.java
index 43b918dbea73..8bcf0571b2d0 100644
--- a/packages/SystemUI/src/com/android/systemui/SysUIToast.java
+++ b/packages/SystemUI/src/com/android/systemui/SysUIToast.java
@@ -15,11 +15,12 @@
*/
package com.android.systemui;
+import static android.widget.Toast.Duration;
+
import android.annotation.StringRes;
import android.content.Context;
import android.view.WindowManager;
import android.widget.Toast;
-import static android.widget.Toast.Duration;
public class SysUIToast {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemBars.java b/packages/SystemUI/src/com/android/systemui/SystemBars.java
index b5093b3ce52a..6edc23be8e23 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemBars.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemBars.java
@@ -14,13 +14,8 @@
package com.android.systemui;
-import android.content.res.Configuration;
-import android.provider.Settings;
import android.util.Log;
-import com.android.systemui.R;
-import com.android.systemui.SystemUI;
-
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index c4bf27b5104a..2dd362e97ccc 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -22,9 +22,9 @@ import android.util.ArrayMap;
import android.util.Log;
import android.view.ViewGroup;
+import com.android.internal.colorextraction.ColorExtractor.GradientColors;
import com.android.internal.util.function.TriConsumer;
import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.colorextraction.ColorExtractor.GradientColors;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.Dependency.DependencyProvider;
import com.android.systemui.classifier.FalsingManager;
@@ -32,20 +32,20 @@ import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.AmbientPulseManager;
import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
-import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 8e29841e887d..ac108becfeb2 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -24,13 +24,13 @@ import android.os.Process;
import android.os.SystemProperties;
import android.util.Slog;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
import com.android.internal.os.BinderInternal;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginManagerImpl;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
public class SystemUIService extends Service {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
index 4bd095de3777..79d4f8d634ce 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java
@@ -31,7 +31,6 @@ import android.os.Handler;
import android.view.View;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
-import android.view.animation.AnimationUtils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
index 96af08b6bf6b..50fefe948aa8 100644
--- a/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/car/CarNotificationEntryManager.java
@@ -17,9 +17,9 @@ package com.android.systemui.car;
import android.content.Context;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
public class CarNotificationEntryManager extends NotificationEntryManager {
public CarNotificationEntryManager(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
index e4b2e07dc81e..09c000b469a7 100644
--- a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
@@ -23,10 +23,10 @@ import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.Dependency.DependencyProvider;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.car.CarFacetButtonController;
import com.android.systemui.statusbar.car.CarStatusBarKeyguardViewManager;
import com.android.systemui.statusbar.car.hvac.HvacController;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java b/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java
index 158deb46f8d2..28a38083218e 100644
--- a/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java
@@ -17,16 +17,7 @@
package com.android.systemui.chooser;
import android.app.Activity;
-import android.app.ActivityManager;
-import android.content.Intent;
import android.os.Bundle;
-import android.os.IBinder;
-import android.util.Log;
-
-import com.android.systemui.R;
-
-import java.lang.Thread;
-import java.util.ArrayList;
/**
* Activity for selecting which application ought to handle an ACTION_SEND intent.
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
index cdf4ba7d99d7..6d13973d23b5 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
@@ -18,7 +18,6 @@ package com.android.systemui.classifier;
import android.os.Build;
import android.os.SystemProperties;
-import android.util.Log;
import android.view.MotionEvent;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
index 71ddba5ffdcc..cb7c998fad8e 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingLog.java
@@ -23,8 +23,6 @@ import android.os.SystemProperties;
import android.util.Log;
import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
index 592a275edaa0..577d57a9990e 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
@@ -24,13 +24,11 @@ import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.DisplayMetrics;
-import android.util.Log;
import android.view.MotionEvent;
import com.android.systemui.R;
import java.util.ArrayDeque;
-import java.util.ArrayList;
/**
* An classifier trying to determine whether it is a human interacting with the phone or not.
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index e2047bf89833..d93ed1785a0a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -22,7 +22,6 @@ import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Handler;
-import android.os.PowerManager;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.keyguard.KeyguardUpdateMonitor;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index ce84b84935c5..01a234544c5b 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -33,8 +33,6 @@ import android.provider.Settings;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
-import java.util.concurrent.atomic.AtomicBoolean;
-
/**
* Controls the screen brightness when dozing.
*/
@@ -66,7 +64,6 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
* --ei brightness_bucket 1}
*/
private int mDebugBrightnessBucket = -1;
- private AtomicBoolean mIsDestroyed = new AtomicBoolean();
@VisibleForTesting
public DozeScreenBrightness(Context context, DozeMachine.Service service,
@@ -89,9 +86,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
Dependency.get(Dependency.BG_HANDLER).post(()-> {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_AOD_BRIGHTNESS);
- if (!mIsDestroyed.get()) {
- mContext.registerReceiverAsUser(this, UserHandle.ALL, filter, null, handler);
- }
+ mContext.registerReceiverAsUser(this, UserHandle.ALL, filter, null, handler);
});
}
}
@@ -129,10 +124,11 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
}
private void onDestroy() {
- mIsDestroyed.set(true);
setLightSensorEnabled(false);
if (mDebuggable) {
- mContext.unregisterReceiver(this);
+ Dependency.get(Dependency.BG_HANDLER).post(()-> {
+ mContext.unregisterReceiver(this);
+ });
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
index 4fc2d9bd344b..25c2c39f3e25 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
@@ -16,9 +16,10 @@
package com.android.systemui.doze;
-import androidx.annotation.VisibleForTesting;
import android.view.Display;
+import androidx.annotation.VisibleForTesting;
+
import com.android.systemui.statusbar.phone.DozeParameters;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
index 3013b969c74b..a0c490951199 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
@@ -16,9 +16,10 @@
package com.android.systemui.doze;
-import androidx.annotation.VisibleForTesting;
import android.view.Display;
+import androidx.annotation.VisibleForTesting;
+
import com.android.systemui.statusbar.phone.DozeParameters;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
index 47f86fed7e69..9a5a5b855999 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
@@ -23,8 +23,6 @@ import android.os.ServiceManager;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.statusbar.phone.DozeParameters;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java b/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
index f06ea451d4d0..84b91bc8e3a1 100644
--- a/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/egg/MLandActivity.java
@@ -19,7 +19,6 @@ package com.android.systemui.egg;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
-import android.view.ViewGroup;
import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 779a86cdc6be..60e39b21680b 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -28,11 +28,12 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Parcelable;
-import androidx.annotation.NonNull;
import android.util.ArrayMap;
import android.view.LayoutInflater;
import android.view.View;
+import androidx.annotation.NonNull;
+
import com.android.settingslib.applications.InterestingConfigChanges;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.Plugin;
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
index e0657c90238f..7d52a9a08c2a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
@@ -43,12 +43,12 @@ import android.util.Slog;
import android.widget.Toast;
import com.android.settingslib.bluetooth.BluetoothCallback;
+import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
-import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
index d833c16c04b3..7bec5c0349f9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
@@ -19,6 +19,7 @@ package com.android.systemui.keyguard;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.systemui.Dependency;
import com.android.systemui.UiOffloadThread;
+
import java.util.ArrayList;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
index 4c98c08222e3..b3481c52d7f2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
@@ -19,8 +19,6 @@ package com.android.systemui.keyguard;
import android.os.Handler;
import android.os.Message;
-import com.android.internal.policy.IKeyguardDrawnCallback;
-
/**
* Dispatches the lifecycles keyguard gets from WindowManager on the main thread.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 22b41a4f9cfa..81247cd2f727 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -16,6 +16,8 @@
package com.android.systemui.keyguard;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
@@ -34,8 +36,6 @@ import com.android.internal.policy.IKeyguardStateCallback;
import com.android.systemui.Dependency;
import com.android.systemui.SystemUIApplication;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
public class KeyguardService extends Service {
static final String TAG = "KeyguardService";
static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index fe1b35609ae5..3b9110d31c6f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1940,11 +1940,6 @@ public class KeyguardViewMediator extends SystemUI {
mContext.getSystemService(Context.STATUS_BAR_SERVICE);
}
- // TODO(b/113914868): investigation log for disappearing home button
- Log.d(TAG, "adjustStatusBarLocked (b/113914868): mShowing=" + mShowing
- + " mStatusBarManager=" + mStatusBarManager + " mOccluded="
- + mOccluded + " isSecure=" + isSecure() + " force=" + forceHideHomeRecentsButtons);
-
if (mStatusBarManager == null) {
Log.w(TAG, "Could not get status bar manager");
} else {
@@ -1961,6 +1956,12 @@ public class KeyguardViewMediator extends SystemUI {
+ " --> flags=0x" + Integer.toHexString(flags));
}
+ // TODO(b/113914868): investigation log for disappearing home button
+ Log.d(TAG, "adjustStatusBarLocked (b/113914868): flags=" + flags
+ + "mShowing=" + mShowing + " mStatusBarManager=" + mStatusBarManager
+ + " mOccluded=" + mOccluded + " isSecure=" + isSecure()
+ + " force=" + forceHideHomeRecentsButtons);
+
mStatusBarManager.disable(flags);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
index 74f770679cc9..6498b9161be7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivityController.java
@@ -28,6 +28,7 @@ import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index ab612dd93dd1..ddd9cbf209d6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -33,10 +33,8 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.MediaStore;
-import android.provider.MediaStore.Audio.AudioColumns;
import android.util.Log;
-import com.android.internal.util.Preconditions;
import com.android.systemui.SystemUI;
import java.io.FileDescriptor;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
index 70b581a78ce4..7792e177b601 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
@@ -23,8 +23,10 @@ import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.UserHandle;
import android.os.UserManager;
+
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.CommandQueue;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
index 9ce2606a2a15..8615e43b73fe 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipDismissViewController.java
@@ -27,6 +27,7 @@ import android.view.View;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.FrameLayout;
+
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.shared.system.WindowManagerWrapper;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 08208e506f24..8c3f43635f72 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -35,6 +35,7 @@ import android.view.IPinnedStackController;
import android.view.IPinnedStackListener;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
+
import com.android.systemui.Dependency;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.pip.BasePipManager;
@@ -42,6 +43,7 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowManagerWrapper;
+
import java.io.PrintWriter;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index b746c192cece..e447defadd08 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -23,15 +23,14 @@ import static android.provider.Settings.ACTION_PICTURE_IN_PICTURE_SETTINGS;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ACTIONS;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_ALLOW_TIMEOUT;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_CONTROLLER_MESSENGER;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_WILL_RESIZE_MENU;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_DISMISS_FRACTION;
-import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MOVEMENT_BOUNDS;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MENU_STATE;
+import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_MOVEMENT_BOUNDS;
import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_STACK_BOUNDS;
-
-import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_NONE;
+import static com.android.systemui.pip.phone.PipMenuActivityController.EXTRA_WILL_RESIZE_MENU;
import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_CLOSE;
import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_FULL;
+import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_NONE;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 56b83247a15e..46d53e410725 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -37,8 +37,10 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Log;
+
import com.android.systemui.pip.phone.PipMediaController.ActionListener;
import com.android.systemui.shared.system.InputConsumerController;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index ce7da79de794..38583564f5b0 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -18,6 +18,7 @@ package com.android.systemui.pip.phone;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+
import static com.android.systemui.Interpolators.FAST_OUT_LINEAR_IN;
import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.systemui.Interpolators.LINEAR_OUT_SLOW_IN;
@@ -42,11 +43,13 @@ import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.view.animation.Interpolator;
+
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.internal.os.SomeArgs;
import com.android.internal.policy.PipSnapAlgorithm;
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.statusbar.FlingAnimationUtils;
+
import java.io.PrintWriter;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
index b9369d39dd51..9aa21f8270b3 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
@@ -18,7 +18,6 @@ package com.android.systemui.pip.phone;
import android.graphics.PointF;
import android.os.Handler;
-import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
index 10206d492e3a..a40b72b30f22 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipControlsView.java
@@ -16,7 +16,6 @@
package com.android.systemui.pip.tv;
-import android.app.ActivityManager;
import android.app.PendingIntent.CanceledException;
import android.app.RemoteAction;
import android.content.Context;
@@ -24,20 +23,15 @@ import android.graphics.Color;
import android.media.session.MediaController;
import android.media.session.PlaybackState;
import android.os.Handler;
-import android.os.RemoteException;
+import android.util.AttributeSet;
import android.util.Log;
-import android.view.View;
import android.view.Gravity;
import android.view.LayoutInflater;
-import android.widget.ImageView;
+import android.view.View;
import android.widget.LinearLayout;
-import android.util.AttributeSet;
import com.android.systemui.R;
-import static android.media.session.PlaybackState.ACTION_PAUSE;
-import static android.media.session.PlaybackState.ACTION_PLAY;
-
import java.util.ArrayList;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index e17e0bca56dc..ca3cdf4bee80 100755
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -49,6 +49,7 @@ import android.view.IPinnedStackController;
import android.view.IPinnedStackListener;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
+
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.UiOffloadThread;
@@ -56,7 +57,7 @@ import com.android.systemui.pip.BasePipManager;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowManagerWrapper;
-import java.io.PrintWriter;
+
import java.util.ArrayList;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
index e437eff28a08..3a5fa2253057 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipMenuActivity.java
@@ -22,7 +22,6 @@ import android.app.Activity;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
import android.os.Bundle;
-import android.view.View;
import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
index ac41b752020b..89ecc6abd623 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
@@ -26,17 +26,15 @@ import android.content.IntentFilter;
import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
import android.graphics.Bitmap;
-import android.graphics.drawable.Icon;
import android.media.MediaMetadata;
import android.media.session.MediaController;
import android.media.session.PlaybackState;
import android.text.TextUtils;
import android.util.Log;
-import android.view.View;
-import com.android.systemui.util.NotificationChannels;
-import com.android.systemui.R;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.systemui.R;
+import com.android.systemui.util.NotificationChannels;
/**
* A notification that informs users that PIP is running and also provides PIP controls.
diff --git a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java
index 5686d801bca2..3f2417638f1a 100644
--- a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java
@@ -1,7 +1,5 @@
package com.android.systemui.power;
-import android.util.Log;
-
public class EnhancedEstimatesImpl implements EnhancedEstimates {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 21eab592098d..b722f9f1d1c1 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -41,6 +41,7 @@ import android.text.style.URLSpan;
import android.util.Log;
import android.util.Slog;
import android.view.View;
+
import androidx.annotation.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
index fc1baeff706e..d3715d04b7bc 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
@@ -15,7 +15,6 @@
package com.android.systemui.privacy
import android.content.Context
-import android.graphics.Color
import android.util.AttributeSet
import android.view.ViewGroup
import android.widget.ImageView
@@ -30,7 +29,13 @@ class OngoingPrivacyChip @JvmOverloads constructor(
defStyleRes: Int = 0
) : LinearLayout(context, attrs, defStyleAttrs, defStyleRes) {
- private lateinit var appName: TextView
+ private val iconMargin =
+ context.resources.getDimensionPixelSize(R.dimen.ongoing_appops_chip_icon_margin)
+ private val iconSize =
+ context.resources.getDimensionPixelSize(R.dimen.ongoing_appops_chip_icon_size)
+ val iconColor = context.resources.getColor(
+ R.color.status_bar_clock_color, context.theme)
+ private lateinit var text: TextView
private lateinit var iconsContainer: LinearLayout
var builder = PrivacyDialogBuilder(context, emptyList<PrivacyItem>())
var privacyList = emptyList<PrivacyItem>()
@@ -43,7 +48,7 @@ class OngoingPrivacyChip @JvmOverloads constructor(
override fun onFinishInflate() {
super.onFinishInflate()
- appName = findViewById(R.id.app_name)
+ text = findViewById(R.id.text_container)
iconsContainer = findViewById(R.id.icons_container)
}
@@ -53,39 +58,52 @@ class OngoingPrivacyChip @JvmOverloads constructor(
iconsContainer.removeAllViews()
dialogBuilder.generateIcons().forEach {
it.mutate()
- it.setTint(Color.WHITE)
- iconsContainer.addView(ImageView(context).apply {
+ it.setTint(iconColor)
+ val image = ImageView(context).apply {
setImageDrawable(it)
- maxHeight = this@OngoingPrivacyChip.height
- })
+ scaleType = ImageView.ScaleType.CENTER_INSIDE
+ }
+ iconsContainer.addView(image, iconSize, iconSize)
+ val lp = image.layoutParams as MarginLayoutParams
+ lp.marginStart = iconMargin
+ image.layoutParams = lp
}
}
- if (privacyList.isEmpty()) {
- return
- } else {
+ if (!privacyList.isEmpty()) {
generateContentDescription()
setIcons(builder, iconsContainer)
- appName.visibility = GONE
- builder.app?.let {
- appName.apply {
- setText(it.applicationName)
- setTextColor(Color.WHITE)
- visibility = VISIBLE
+ text.visibility = if (builder.types.size == 1) VISIBLE else GONE
+ if (builder.types.size == 1) {
+ if (builder.app != null) {
+ text.setText(builder.app?.applicationName)
+ } else {
+ text.text = context.getString(R.string.ongoing_privacy_chip_multiple_apps,
+ builder.appsAndTypes.size)
}
}
+ } else {
+ text.visibility = GONE
+ iconsContainer.removeAllViews()
}
requestLayout()
}
private fun generateContentDescription() {
- val typesText = builder.generateTypesText()
- if (builder.app != null) {
- contentDescription = context.getString(R.string.ongoing_privacy_chip_content_single_app,
- builder.app?.applicationName, typesText)
- } else {
+ val typesText = builder.joinTypes()
+ if (builder.types.size > 1) {
contentDescription = context.getString(
R.string.ongoing_privacy_chip_content_multiple_apps, typesText)
+ } else {
+ if (builder.app != null) {
+ contentDescription =
+ context.getString(R.string.ongoing_privacy_chip_content_single_app,
+ builder.app?.applicationName, typesText)
+ } else {
+ contentDescription = context.getString(
+ R.string.ongoing_privacy_chip_content_multiple_apps_single_op,
+ builder.appsAndTypes.size, typesText)
+ }
}
}
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
index 1d0e16ed3334..f6a95af4a075 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
@@ -18,10 +18,10 @@ import android.app.AlertDialog
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
-import android.graphics.drawable.Drawable
+import android.content.Intent
+import android.content.res.ColorStateList
import android.view.LayoutInflater
import android.view.View
-import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
@@ -34,29 +34,25 @@ class OngoingPrivacyDialog constructor(
val dialogBuilder: PrivacyDialogBuilder
) {
- val iconHeight = context.resources.getDimensionPixelSize(
+ val iconSize = context.resources.getDimensionPixelSize(
R.dimen.ongoing_appops_dialog_icon_height)
- val textMargin = context.resources.getDimensionPixelSize(
- R.dimen.ongoing_appops_dialog_text_margin)
val iconColor = context.resources.getColor(
com.android.internal.R.color.text_color_primary, context.theme)
+ companion object {
+ private const val MAX_ITEMS = 10
+ }
fun createDialog(): Dialog {
- val builder = AlertDialog.Builder(context)
- .setNeutralButton(R.string.ongoing_privacy_dialog_open_settings, null)
- if (dialogBuilder.app != null) {
- builder.setPositiveButton(R.string.ongoing_privacy_dialog_open_app,
+ val builder = AlertDialog.Builder(context).apply {
+ setNegativeButton(R.string.ongoing_privacy_dialog_cancel, null)
+ setPositiveButton(R.string.ongoing_privacy_dialog_open_settings,
object : DialogInterface.OnClickListener {
- val intent = context.packageManager
- .getLaunchIntentForPackage(dialogBuilder.app.packageName)
+ val intent = Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE)
override fun onClick(dialog: DialogInterface?, which: Int) {
Dependency.get(ActivityStarter::class.java).startActivity(intent, false)
}
})
- builder.setNegativeButton(R.string.ongoing_privacy_dialog_cancel, null)
- } else {
- builder.setPositiveButton(R.string.ongoing_privacy_dialog_okay, null)
}
builder.setView(getContentView())
return builder.create()
@@ -66,44 +62,67 @@ class OngoingPrivacyDialog constructor(
val layoutInflater = LayoutInflater.from(context)
val contentView = layoutInflater.inflate(R.layout.ongoing_privacy_dialog_content, null)
- val iconsContainer = contentView.findViewById(R.id.icons_container) as LinearLayout
- val textContainer = contentView.findViewById(R.id.text_container) as LinearLayout
+ val title = contentView.findViewById(R.id.title) as TextView
+ val appsList = contentView.findViewById(R.id.items_container) as LinearLayout
+
+ title.setText(dialogBuilder.getDialogTitle())
- addIcons(dialogBuilder, iconsContainer)
- val lm = ViewGroup.MarginLayoutParams(
- ViewGroup.MarginLayoutParams.WRAP_CONTENT,
- ViewGroup.MarginLayoutParams.WRAP_CONTENT)
- lm.topMargin = textMargin
- val now = System.currentTimeMillis()
- dialogBuilder.generateText(now).forEach {
- val text = layoutInflater.inflate(R.layout.ongoing_privacy_text_item, null) as TextView
- text.setText(it)
- textContainer.addView(text, lm)
+ val numItems = dialogBuilder.appsAndTypes.size
+ for (i in 0..(numItems - 1)) {
+ if (i >= MAX_ITEMS) break
+ val item = dialogBuilder.appsAndTypes[i]
+ addAppItem(appsList, item.first, item.second, dialogBuilder.types.size > 1)
+ }
+
+ if (numItems > MAX_ITEMS) {
+ val overflow = contentView.findViewById(R.id.overflow) as LinearLayout
+ overflow.visibility = View.VISIBLE
+ val overflowText = overflow.findViewById(R.id.app_name) as TextView
+ overflowText.text = context.resources.getQuantityString(
+ R.plurals.ongoing_privacy_dialog_overflow_text,
+ numItems - MAX_ITEMS,
+ numItems - MAX_ITEMS
+ )
+ val overflowPlus = overflow.findViewById(R.id.app_icon) as ImageView
+ overflowPlus.apply {
+ imageTintList = ColorStateList.valueOf(iconColor)
+ setImageDrawable(context.getDrawable(R.drawable.plus))
+ }
}
+
return contentView
}
- private fun addIcons(dialogBuilder: PrivacyDialogBuilder, iconsContainer: LinearLayout) {
+ private fun addAppItem(
+ itemList: LinearLayout,
+ app: PrivacyApplication,
+ types: List<PrivacyType>,
+ showIcons: Boolean = true
+ ) {
+ val layoutInflater = LayoutInflater.from(context)
+ val item = layoutInflater.inflate(R.layout.ongoing_privacy_dialog_item, itemList, false)
+ val appIcon = item.findViewById(R.id.app_icon) as ImageView
+ val appName = item.findViewById(R.id.app_name) as TextView
+ val icons = item.findViewById(R.id.icons) as LinearLayout
- fun LinearLayout.addIcon(icon: Drawable) {
- val image = ImageView(context).apply {
- setImageDrawable(icon.apply {
- setBounds(0, 0, iconHeight, iconHeight)
- maxHeight = this@addIcon.height
- })
- adjustViewBounds = true
- }
- addView(image, LinearLayout.LayoutParams.WRAP_CONTENT,
- LinearLayout.LayoutParams.MATCH_PARENT)
+ app.icon?.let {
+ appIcon.setImageDrawable(it)
}
- dialogBuilder.generateIcons().forEach {
- it.mutate()
- it.setTint(iconColor)
- iconsContainer.addIcon(it)
- }
- dialogBuilder.app.let {
- it?.icon?.let { iconsContainer.addIcon(it) }
+ appName.text = app.applicationName
+ if (showIcons) {
+ dialogBuilder.generateIconsForApp(types).forEach {
+ it.setBounds(0, 0, iconSize, iconSize)
+ val image = ImageView(context).apply {
+ imageTintList = ColorStateList.valueOf(iconColor)
+ setImageDrawable(it)
+ }
+ icons.addView(image, iconSize, LinearLayout.LayoutParams.WRAP_CONTENT)
+ }
+ icons.visibility = View.VISIBLE
+ } else {
+ icons.visibility = View.GONE
}
+ itemList.addView(item)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
index 2f86f78d7669..519df19f0e20 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
@@ -15,60 +15,53 @@
package com.android.systemui.privacy
import android.content.Context
+import android.graphics.drawable.Drawable
import com.android.systemui.R
-import java.lang.IllegalStateException
-import java.lang.Math.max
class PrivacyDialogBuilder(val context: Context, itemsList: List<PrivacyItem>) {
- companion object {
- val MILLIS_IN_MINUTE: Long = 1000 * 60
- }
- private val itemsByType: Map<PrivacyType, List<PrivacyItem>>
+ val appsAndTypes: List<Pair<PrivacyApplication, List<PrivacyType>>>
+ val types: List<PrivacyType>
val app: PrivacyApplication?
+ private val separator = context.getString(R.string.ongoing_privacy_dialog_separator)
+ private val lastSeparator = context.getString(R.string.ongoing_privacy_dialog_last_separator)
init {
- itemsByType = itemsList.groupBy { it.privacyType }
- val apps = itemsList.map { it.application }.distinct()
- val singleApp = apps.size == 1
- app = if (singleApp) apps.get(0) else null
+ appsAndTypes = itemsList.groupBy({ it.application }, { it.privacyType })
+ .toList()
+ .sortedWith(compareBy({ -it.second.size }, { it.first }))
+ types = itemsList.map { it.privacyType }.distinct().sorted()
+ val singleApp = appsAndTypes.size == 1
+ app = if (singleApp) appsAndTypes[0].first else null
+ }
+
+ fun generateIconsForApp(types: List<PrivacyType>): List<Drawable> {
+ return types.sorted().map { it.getIcon(context) }
}
- private fun buildTextForItem(type: PrivacyType, now: Long): String {
- val items = itemsByType.getOrDefault(type, emptyList<PrivacyItem>())
- return when (items.size) {
- 0 -> throw IllegalStateException("List cannot be empty")
- 1 -> {
- val item = items.get(0)
- val minutesUsed = max(((now - item.timeStarted) / MILLIS_IN_MINUTE).toInt(), 1)
- context.getString(R.string.ongoing_privacy_dialog_app_item,
- item.application.applicationName, type.getName(context), minutesUsed)
- }
- else -> {
- val apps = items.map { it.application.applicationName }.joinToString()
- context.getString(R.string.ongoing_privacy_dialog_apps_item,
- apps, type.getName(context))
- }
+ fun generateIcons() = types.map { it.getIcon(context) }
+
+ private fun <T> List<T>.joinWithAnd(): StringBuilder {
+ return subList(0, size - 1).joinTo(StringBuilder(), separator = separator).apply {
+ append(lastSeparator)
+ append(this@joinWithAnd.last())
}
}
- private fun buildTextForApp(types: Set<PrivacyType>): List<String> {
- app?.let {
- val typesText = types.map { it.getName(context) }.sorted().joinToString()
- return listOf(context.getString(R.string.ongoing_privacy_dialog_single_app,
- it.applicationName, typesText))
- } ?: throw IllegalStateException("There has to be a single app")
+ fun joinTypes(): String {
+ return when (types.size) {
+ 0 -> ""
+ 1 -> types[0].getName(context)
+ else -> types.map { it.getName(context) }.joinWithAnd().toString()
+ }
}
- fun generateText(now: Long): List<String> {
- if (app == null || itemsByType.keys.size == 1) {
- return itemsByType.keys.map { buildTextForItem(it, now) }
+ fun getDialogTitle(): String {
+ if (app != null) {
+ return context.getString(R.string.ongoing_privacy_dialog_single_app_title, joinTypes())
} else {
- return buildTextForApp(itemsByType.keys)
+ return context.getString(R.string.ongoing_privacy_dialog_multiple_apps_title,
+ joinTypes())
}
}
-
- fun generateTypesText() = itemsByType.keys.map { it.getName(context) }.sorted().joinToString()
-
- fun generateIcons() = itemsByType.keys.map { it.getIcon(context) }
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
index f4099021a0bd..85e99f05f895 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
@@ -23,22 +23,27 @@ import com.android.systemui.R
typealias Privacy = PrivacyType
enum class PrivacyType(val nameId: Int, val iconId: Int) {
- TYPE_CAMERA(R.string.privacy_type_camera, com.android.internal.R.drawable.ic_camera),
+ TYPE_CAMERA(R.string.privacy_type_camera, R.drawable.stat_sys_camera),
TYPE_LOCATION(R.string.privacy_type_location, R.drawable.stat_sys_location),
- TYPE_MICROPHONE(R.string.privacy_type_microphone, R.drawable.ic_mic_26dp);
+ TYPE_MICROPHONE(R.string.privacy_type_microphone, R.drawable.stat_sys_mic_none);
fun getName(context: Context) = context.resources.getString(nameId)
- fun getIcon(context: Context) = context.resources.getDrawable(iconId, null)
+ fun getIcon(context: Context) = context.resources.getDrawable(iconId, context.theme)
}
data class PrivacyItem(
val privacyType: PrivacyType,
- val application: PrivacyApplication,
- val timeStarted: Long
+ val application: PrivacyApplication
)
-data class PrivacyApplication(val packageName: String, val context: Context) {
+data class PrivacyApplication(val packageName: String, val context: Context)
+ : Comparable<PrivacyApplication> {
+
+ override fun compareTo(other: PrivacyApplication): Int {
+ return applicationName.compareTo(other.applicationName)
+ }
+
var icon: Drawable? = null
var applicationName: String
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
index 5141e5055e9b..3fa3e8eec0ab 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -95,7 +95,7 @@ class PrivacyItemController(val context: Context, val callback: Callback) {
else -> return null
}
val app = PrivacyApplication(appOpItem.packageName, context)
- return PrivacyItem(type, app, appOpItem.timeStarted)
+ return PrivacyItem(type, app)
}
// Used by containing class to get notified of changes
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AlphaControlledSignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/AlphaControlledSignalTileView.java
index 2c7ec70a5fff..6a6f5728fc5b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/AlphaControlledSignalTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/AlphaControlledSignalTileView.java
@@ -19,6 +19,7 @@ package com.android.systemui.qs;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
+
import com.android.systemui.qs.tileimpl.SlashImageView;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java b/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java
index 767fd9efd4f0..1195184050e3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/AutoSizingList.java
@@ -23,6 +23,7 @@ import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
+
import com.android.systemui.R;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
index 376e6ae16cc8..c1aa7069d6ba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
@@ -20,7 +20,6 @@ import android.service.quicksettings.Tile;
import android.widget.ImageView;
import com.android.settingslib.graph.SignalDrawable;
-import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSTile.Icon;
import com.android.systemui.plugins.qs.QSTile.State;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java b/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
index 6aad47927a15..afce69e7f2d0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/DataUsageGraph.java
@@ -18,7 +18,6 @@ package com.android.systemui.qs;
import android.content.Context;
import android.content.res.Resources;
-import android.content.res.ColorStateList;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
index aa2f8d171143..d5c5ba401e99 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
@@ -6,10 +6,10 @@ import android.content.res.TypedArray;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
+
import com.android.systemui.R;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 1451e71e2df5..dbd304233601 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -23,14 +23,11 @@ import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Point;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
import com.android.systemui.R;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.qs.customize.QSCustomizer;
-import com.android.systemui.statusbar.CommandQueue;
/**
* Wrapper view with background which contains {@link QSPanel} and {@link BaseStatusBarHeader}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
index ddd991023273..dab0efe10b5d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailItems.java
@@ -32,6 +32,7 @@ import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
+
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSTile;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index 84eb3da51bcf..b597a72ba899 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -15,9 +15,10 @@
*/
package com.android.systemui.qs;
-import androidx.annotation.Nullable;
import android.view.View;
+import androidx.annotation.Nullable;
+
/**
* The bottom footer of the quick settings panel.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index f147fb3054b7..8903a38dc600 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -28,8 +28,6 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
import android.os.Bundle;
import android.os.UserManager;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
@@ -40,6 +38,9 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.keyguard.CarrierText;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index f9971d83addc..953eb70cac5d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -22,8 +22,6 @@ import android.app.Fragment;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
@@ -34,6 +32,9 @@ import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout.LayoutParams;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -42,9 +43,9 @@ import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
-import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
public class QSFragment extends Fragment implements QS, CommandQueue.Callbacks {
private static final String TAG = "QS";
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index cf63e478312c..f1f0f698ab72 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -17,6 +17,7 @@
package com.android.systemui.qs;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+
import static com.android.systemui.qs.tileimpl.QSTileImpl.getColorForState;
import android.annotation.Nullable;
@@ -30,7 +31,6 @@ import android.os.Handler;
import android.os.Message;
import android.service.quicksettings.Tile;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java b/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java
index 7ebab0bfce24..001cbbac5606 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java
@@ -17,7 +17,6 @@ package com.android.systemui.qs;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
-import androidx.core.widget.NestedScrollView;
import android.util.Property;
import android.view.MotionEvent;
import android.view.View;
@@ -25,6 +24,8 @@ import android.view.ViewConfiguration;
import android.view.ViewParent;
import android.widget.LinearLayout;
+import androidx.core.widget.NestedScrollView;
+
import com.android.systemui.R;
import com.android.systemui.qs.touch.OverScroll;
import com.android.systemui.qs.touch.SwipeDetector;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
index 8f3a7b3c04e9..e2e943a369c2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java
@@ -33,8 +33,8 @@ import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
import android.view.View.OnClickListener;
+import android.view.ViewGroup;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
@@ -46,8 +46,6 @@ import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.SecurityController;
-import static android.provider.Settings.ACTION_VPN_SETTINGS;
-
public class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListener {
protected static final String TAG = "QSSecurityFooter";
protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index cefeeb526968..d1c2df53b5a5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -31,14 +31,14 @@ import android.util.Log;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.plugins.qs.QSFactory;
-import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.external.TileLifecycleManager;
import com.android.systemui.qs.external.TileServices;
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
+import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.phone.AutoTileManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarIconController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index e3f85d93b8da..427f638b0d30 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -325,15 +325,10 @@ public class QuickStatusBarHeader extends RelativeLayout implements
newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE;
mBatteryMeterView.useWallpaperTextColor(shouldUseWallpaperTextColor);
mClockView.useWallpaperTextColor(shouldUseWallpaperTextColor);
-
- MarginLayoutParams lm = (MarginLayoutParams) mPrivacyChip.getLayoutParams();
- int sideMargins = lm.leftMargin;
- int topBottomMargins = (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)
- ? 0 : sideMargins;
- lm.setMargins(sideMargins, topBottomMargins, sideMargins, topBottomMargins);
- mPrivacyChip.setLayoutParams(lm);
}
+
+
@Override
public void onRtlPropertiesChanged(int layoutDirection) {
super.onRtlPropertiesChanged(layoutDirection);
@@ -378,6 +373,15 @@ 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();
}
@@ -729,7 +733,8 @@ public class QuickStatusBarHeader extends RelativeLayout implements
public void setMargins(int sideMargins) {
for (int i = 0; i < getChildCount(); i++) {
View v = getChildAt(i);
- if (v == mSystemIconsView || v == mQuickQsStatusIcons || v == mHeaderQsPanel) {
+ if (v == mSystemIconsView || v == mQuickQsStatusIcons || v == mHeaderQsPanel
+ || v == mPrivacyChip) {
continue;
}
RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) v.getLayoutParams();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
index f6b08b05bf38..0389030a17b2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
@@ -16,14 +16,14 @@ package com.android.systemui.qs.car;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
-import androidx.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
-import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
+import androidx.annotation.Nullable;
+
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
index 2d9e4d7fc22b..3e82c54dc811 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
@@ -22,14 +22,15 @@ import android.animation.ValueAnimator;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-import androidx.recyclerview.widget.GridLayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.recyclerview.widget.GridLayoutManager;
+
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSFooter;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
index 9b225bb9f18b..083a7471c3c1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
@@ -16,11 +16,12 @@ package com.android.systemui.qs.car;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
-import androidx.annotation.IdRes;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
+import androidx.annotation.IdRes;
+
import com.android.settingslib.Utils;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index dc17dd8fee63..64ad95c6eaea 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -20,13 +20,8 @@ import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.res.Configuration;
-import android.graphics.Point;
import android.os.Bundle;
-import androidx.recyclerview.widget.DefaultItemAnimator;
-import androidx.recyclerview.widget.GridLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
@@ -37,6 +32,10 @@ import android.widget.LinearLayout;
import android.widget.Toolbar;
import android.widget.Toolbar.OnMenuItemClickListener;
+import androidx.recyclerview.widget.DefaultItemAnimator;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settingslib.Utils;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 15d2e66a82ce..a29e93a57c69 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -23,13 +23,6 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.ColorDrawable;
import android.os.Handler;
-import androidx.core.view.ViewCompat;
-import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.ItemDecoration;
-import androidx.recyclerview.widget.RecyclerView.State;
-import androidx.recyclerview.widget.RecyclerView.ViewHolder;
-import androidx.recyclerview.widget.ItemTouchHelper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -39,6 +32,14 @@ import android.view.accessibility.AccessibilityManager;
import android.widget.FrameLayout;
import android.widget.TextView;
+import androidx.core.view.ViewCompat;
+import androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup;
+import androidx.recyclerview.widget.ItemTouchHelper;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.ItemDecoration;
+import androidx.recyclerview.widget.RecyclerView.State;
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index bb65bedd8aeb..89066651084d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -15,6 +15,9 @@
*/
package com.android.systemui.qs.external;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
+
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Intent;
@@ -41,13 +44,11 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile.State;
-import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
import com.android.systemui.qs.QSTileHost;
-import java.util.Objects;
+import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
+import java.util.Objects;
public class CustomTile extends QSTileImpl<State> implements TileChangeListener {
public static final String PREFIX = "custom(";
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
index 451e1f6ca827..2345667f0409 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
@@ -16,9 +16,7 @@
package com.android.systemui.qs.external;
import android.os.IBinder;
-import android.service.quicksettings.IQSService;
import android.service.quicksettings.IQSTileService;
-import android.service.quicksettings.Tile;
import android.util.Log;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileColorPicker.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileColorPicker.java
index 75dd0d9e565d..1caab5aa77ef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileColorPicker.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileColorPicker.java
@@ -18,7 +18,9 @@ package com.android.systemui.qs.external;
import android.content.Context;
import android.content.res.ColorStateList;
import android.service.quicksettings.Tile;
+
import androidx.annotation.VisibleForTesting;
+
import com.android.systemui.R;
public class TileColorPicker {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index 4e0f38fc4662..305fbf2e3e98 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -15,15 +15,14 @@
*/
package com.android.systemui.qs.external;
-import android.app.AppGlobals;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
-import android.content.ServiceConnection;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
@@ -34,10 +33,10 @@ import android.service.quicksettings.IQSService;
import android.service.quicksettings.IQSTileService;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
-import androidx.annotation.VisibleForTesting;
import android.util.ArraySet;
import android.util.Log;
-import com.android.systemui.qs.external.PackageManagerAdapter;
+
+import androidx.annotation.VisibleForTesting;
import java.util.Objects;
import java.util.Set;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index 9f9fe39bab6c..416c2da53606 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -30,9 +30,10 @@ import android.os.UserHandle;
import android.service.quicksettings.IQSTileService;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
-import androidx.annotation.VisibleForTesting;
import android.util.Log;
+import androidx.annotation.VisibleForTesting;
+
import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index ac7ef5dc308e..b2f60436fecd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -20,8 +20,11 @@ import android.util.Log;
import android.view.ContextThemeWrapper;
import com.android.systemui.R;
-import com.android.systemui.plugins.qs.*;
+import com.android.systemui.plugins.qs.QSFactory;
+import com.android.systemui.plugins.qs.QSIconView;
+import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTileView;
+import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.tiles.AirplaneModeTile;
import com.android.systemui.qs.tiles.BatterySaverTile;
@@ -41,7 +44,6 @@ import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.qs.tiles.UserTile;
import com.android.systemui.qs.tiles.WifiTile;
import com.android.systemui.qs.tiles.WorkModeTile;
-import com.android.systemui.qs.QSTileHost;
import com.android.systemui.util.leak.GarbageMonitor;
public class QSFactoryImpl implements QSFactory {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
index 9dd5d8fbc776..e2453128d4b0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java
@@ -34,8 +34,8 @@ import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSIconView;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.State;
-
import com.android.systemui.qs.AlphaControlledSignalTileView.AlphaControlledSlashImageView;
+
import java.util.Objects;
public class QSIconViewImpl extends QSIconView {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java
index a3e9afd366fd..72c68ce12ca4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java
@@ -17,9 +17,10 @@ package com.android.systemui.qs.tileimpl;
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.drawable.Drawable;
-import androidx.annotation.NonNull;
import android.widget.ImageView;
+import androidx.annotation.NonNull;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.plugins.qs.QSTile.SlashState;
import com.android.systemui.qs.SlashDrawable;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index cd0031173f8b..c62a592be8e2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -16,8 +16,6 @@
package com.android.systemui.qs.tiles;
-import static com.android.settingslib.graph.BluetoothDeviceLayerDrawable.createLayerDrawable;
-
import android.annotation.Nullable;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index b93f1c208c11..c13a07fdd15e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -22,14 +22,13 @@ import android.provider.Settings.Secure;
import android.service.quicksettings.Tile;
import android.widget.Switch;
-import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.R.drawable;
-import com.android.systemui.qs.QSHost;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
-import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.SecureSetting;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
/** Quick settings tile: Invert colors **/
public class ColorInversionTile extends QSTileImpl<BooleanState> {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index ace361bdb4e6..fd8b9c9534dc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -18,6 +18,7 @@ import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.service.quicksettings.Tile;
import android.widget.Switch;
+
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.Prefs;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
index 7bcc6d7b93a9..55785586464f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
@@ -16,11 +16,10 @@
package com.android.systemui.qs.tiles;
-import android.annotation.ColorInt;
import android.content.Context;
+import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.content.res.ColorStateList;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 3c565ef9d07f..a639a9525dd4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -29,13 +29,11 @@ import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
-import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.qs.QSHost;
-import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import java.util.Arrays;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index d7f2a2642180..b5f2d005e8e4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -27,8 +27,8 @@ import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.R.drawable;
import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.qs.QSHost;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.LocationController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
index 9edd65e14bf2..a365e4c53b0d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -22,17 +22,15 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
import android.nfc.NfcAdapter;
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.widget.Switch;
-import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
-import com.android.systemui.qs.QSHost;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
/** Quick settings tile: Enable/Disable NFC **/
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index c41f087aa76b..90890c076a3c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -21,19 +21,21 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Intent;
+import android.hardware.display.ColorDisplayManager;
import android.metrics.LogMaker;
import android.provider.Settings;
import android.service.quicksettings.Tile;
-import androidx.annotation.StringRes;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Switch;
+import androidx.annotation.StringRes;
+
import com.android.internal.app.ColorDisplayController;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
-import com.android.systemui.qs.QSHost;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import java.text.DateFormat;
@@ -53,7 +55,6 @@ public class NightDisplayTile extends QSTileImpl<BooleanState>
private static final String PATTERN_HOUR_MINUTE = "h:mm a";
private static final String PATTERN_HOUR_NINUTE_24 = "HH:mm";
-
private ColorDisplayController mController;
private boolean mIsListening;
@@ -64,7 +65,7 @@ public class NightDisplayTile extends QSTileImpl<BooleanState>
@Override
public boolean isAvailable() {
- return ColorDisplayController.isAvailable(mContext);
+ return ColorDisplayManager.isNightDisplayAvailable(mContext);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index 28b047bad71d..634581638c32 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -19,17 +19,15 @@ package com.android.systemui.qs.tiles;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
-
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.widget.Switch;
-import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.qs.QSHost;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.RotationLockController;
import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
index ad7d1b6b4689..64fe54aa656d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
@@ -30,7 +30,6 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.internal.util.ArrayUtils;
-import com.android.settingslib.drawable.UserIconDrawable;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.UserAvatarView;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
index bde1c98d023c..e5c51a66fafa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserTile.java
@@ -24,9 +24,9 @@ import android.util.Pair;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.qs.DetailAdapter;
-import com.android.systemui.qs.QSHost;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.State;
+import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/touch/SwipeDetector.java b/packages/SystemUI/src/com/android/systemui/qs/touch/SwipeDetector.java
index 911bea67b8b4..e7161e1deace 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/touch/SwipeDetector.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/touch/SwipeDetector.java
@@ -19,12 +19,13 @@ import static android.view.MotionEvent.INVALID_POINTER_ID;
import android.content.Context;
import android.graphics.PointF;
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
/**
* One dimensional scroll/drag/swipe gesture detector.
*
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
index 661b958d4865..958695d3b2ee 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
@@ -31,6 +31,7 @@ import android.os.RemoteException;
import android.util.Log;
import android.view.Display;
import android.widget.Toast;
+
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 19f76759ead7..1b89324209de 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -17,9 +17,9 @@
package com.android.systemui.recents;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_UP;
-import static android.view.MotionEvent.ACTION_CANCEL;
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
@@ -42,6 +42,7 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
import android.view.MotionEvent;
+
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.Prefs;
@@ -55,6 +56,7 @@ import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.CallbackController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index de22d219d4aa..0702d74506fd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -20,9 +20,11 @@ import android.content.ContentResolver;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.provider.Settings;
+
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.CommandQueue;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
index 8a04c11f551a..3efed3fe2c4d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
@@ -18,7 +18,9 @@ package com.android.systemui.recents;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
+
import com.android.systemui.SysUiServiceProvider;
+
import java.io.PrintWriter;
interface RecentsImplementation {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index af0ebdc1306a..34f3c606be62 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -19,16 +19,17 @@ package com.android.systemui.recents;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static com.android.systemui.Prefs.Key.HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE;
import static com.android.systemui.Prefs.Key.DISMISSED_RECENTS_SWIPE_UP_ONBOARDING_COUNT;
+import static com.android.systemui.Prefs.Key.HAS_DISMISSED_RECENTS_QUICK_SCRUB_ONBOARDING_ONCE;
import static com.android.systemui.Prefs.Key.HAS_SEEN_RECENTS_QUICK_SCRUB_ONBOARDING;
import static com.android.systemui.Prefs.Key.HAS_SEEN_RECENTS_SWIPE_UP_ONBOARDING;
import static com.android.systemui.Prefs.Key.OVERVIEW_OPENED_COUNT;
import static com.android.systemui.Prefs.Key.OVERVIEW_OPENED_FROM_HOME_COUNT;
-import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
import static com.android.systemui.shared.system.LauncherEventUtil.DISMISS;
-import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_QUICK_SCRUB_ONBOARDING_TIP;
+import static com.android.systemui.shared.system.LauncherEventUtil
+ .RECENTS_QUICK_SCRUB_ONBOARDING_TIP;
import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_SWIPE_UP_ONBOARDING_TIP;
+import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
import android.annotation.StringRes;
import android.annotation.TargetApi;
@@ -45,9 +46,9 @@ import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.drawable.ShapeDrawable;
import android.os.Build;
+import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserManager;
-import android.os.RemoteException;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -64,6 +65,7 @@ import com.android.systemui.R;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
+
import java.io.PrintWriter;
import java.util.Collections;
import java.util.HashSet;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index f92c50a93f69..216b9409521f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -16,6 +16,9 @@
package com.android.systemui.recents;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
+
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
@@ -50,9 +53,6 @@ import com.android.systemui.util.leak.RotationUtils;
import java.util.ArrayList;
-import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
-import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
-
public class ScreenPinningRequest implements View.OnClickListener {
private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java b/packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java
index af8c2d08f4b4..ef4e19559f1f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/TriangleShape.java
@@ -19,6 +19,7 @@ package com.android.systemui.recents;
import android.graphics.Outline;
import android.graphics.Path;
import android.graphics.drawable.shapes.PathShape;
+
import androidx.annotation.NonNull;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 3ed5f70b8915..79228b9c369e 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -43,7 +43,6 @@ import android.widget.ImageView;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.systemui.Dependency;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
index 2ae53b5d81fe..0374a013a90c 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
@@ -18,7 +18,6 @@ package com.android.systemui.settings;
import android.app.Activity;
import android.os.Bundle;
-import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index 64fa8f86c5f6..07675e248906 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -26,6 +26,7 @@ import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.systemui.SystemUI;
import com.android.systemui.recents.Recents;
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java
index 8ec862e1fdec..156964ac326d 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java
@@ -19,6 +19,7 @@ package com.android.systemui.shortcut;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
+
import com.android.internal.policy.IShortcutService;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index ea194a70adf2..cd2074fd64b8 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -26,9 +26,11 @@ import android.view.IDockedStackListener;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManagerGlobal;
+
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.recents.Recents;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index fa01af68364e..7a7d1f6b1f04 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -55,6 +55,7 @@ import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
import android.widget.FrameLayout;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.policy.DividerSnapAlgorithm;
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
index b7a5d31a324b..2486d6534e8d 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
@@ -16,12 +16,6 @@
package com.android.systemui.stackdivider;
-import android.content.Context;
-import android.graphics.PixelFormat;
-import android.os.Binder;
-import android.view.View;
-import android.view.WindowManager;
-
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -32,6 +26,12 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.os.Binder;
+import android.view.View;
+import android.view.WindowManager;
+
/**
* Manages the window parameters of the docked stack divider.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
index f66db48f441c..c6ac309a0f4e 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
@@ -16,7 +16,8 @@
package com.android.systemui.stackdivider;
-import static com.android.systemui.stackdivider.ForcedResizableInfoActivity.EXTRA_FORCED_RESIZEABLE_REASON;
+import static com.android.systemui.stackdivider.ForcedResizableInfoActivity
+ .EXTRA_FORCED_RESIZEABLE_REASON;
import android.app.ActivityOptions;
import android.content.Context;
@@ -25,6 +26,7 @@ import android.os.Handler;
import android.os.UserHandle;
import android.util.ArraySet;
import android.widget.Toast;
+
import com.android.systemui.R;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index 600964e98b84..228aab5e3eec 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -18,7 +18,6 @@ package com.android.systemui.stackdivider;
import static android.view.WindowManager.DOCKED_INVALID;
-import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.graphics.Rect;
import android.os.RemoteException;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 00e0b954d7be..7f39e474f6c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -62,11 +62,13 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
+
import com.android.internal.app.AssistUtils;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settingslib.Utils;
import com.android.systemui.R;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 1f576342d5cd..a188c5ae7538 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -40,7 +40,6 @@ import android.widget.ImageView;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.KeyguardAffordanceHelper;
/**
* An ImageView which does not have overlapping renderings commands and therefore does not need a
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NeutralGoodDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/NeutralGoodDrawable.java
index cdb0514a2686..8642ca4c7d33 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NeutralGoodDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NeutralGoodDrawable.java
@@ -17,14 +17,11 @@
package com.android.systemui.statusbar;
import android.content.Context;
-import android.content.res.Resources.Theme;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
+
import com.android.settingslib.Utils;
import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java
index 62c21dc17386..ecd9814c3073 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLifetimeExtender.java
@@ -1,9 +1,9 @@
package com.android.systemui.statusbar;
-import com.android.systemui.statusbar.notification.NotificationData;
-
import androidx.annotation.NonNull;
+import com.android.systemui.statusbar.notification.NotificationData;
+
/**
* Interface for anything that may need to keep notifications managed even after
* {@link NotificationListener} removes it. The lifetime extender is in charge of performing the
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
index 5c8f4cbf6078..0e9f950f54ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
@@ -16,11 +16,8 @@
package com.android.systemui.statusbar;
import android.content.Intent;
-import android.os.Handler;
-import android.view.View;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
-import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
index 47b7fe9d7277..f23ae3f6bfb7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationUiAdjustment.java
@@ -22,10 +22,10 @@ import android.app.RemoteInput;
import android.graphics.drawable.Icon;
import android.text.TextUtils;
-import com.android.systemui.statusbar.notification.NotificationData;
-
import androidx.annotation.VisibleForTesting;
+import com.android.systemui.statusbar.notification.NotificationData;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -53,7 +53,8 @@ public class NotificationUiAdjustment {
public static NotificationUiAdjustment extractFromNotificationEntry(
NotificationData.Entry entry) {
- return new NotificationUiAdjustment(entry.key, entry.smartActions, entry.smartReplies);
+ return new NotificationUiAdjustment(
+ entry.key, entry.systemGeneratedSmartActions, entry.smartReplies);
}
public static boolean needReinflate(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java
index 5090f74d4019..f1a891b95eaa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java
@@ -15,10 +15,9 @@
package com.android.systemui.statusbar;
import android.content.Context;
-import android.net.ConnectivityManager;
import android.graphics.Rect;
+import android.net.ConnectivityManager;
import android.os.Bundle;
-import android.provider.Settings;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.text.TextUtils;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
index 7f63191c9131..929f43e01c0f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
@@ -16,10 +16,6 @@
package com.android.systemui.statusbar;
-import com.android.internal.util.Preconditions;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.policy.RemoteInputView;
-
import android.app.Notification;
import android.app.RemoteInput;
import android.content.Context;
@@ -27,6 +23,10 @@ import android.os.SystemProperties;
import android.util.ArrayMap;
import android.util.Pair;
+import com.android.internal.util.Preconditions;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.policy.RemoteInputView;
+
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
index 3bc434280c51..cb9060bc9574 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
@@ -28,16 +28,14 @@ import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import androidx.core.graphics.ColorUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
-import android.view.animation.Interpolator;
+
+import androidx.core.graphics.ColorUtils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.colorextraction.ColorExtractor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
index fb888ddc5f13..758c33a5aabe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SmartReplyController.java
@@ -16,13 +16,11 @@
package com.android.systemui.statusbar;
import android.os.RemoteException;
-import android.service.notification.StatusBarNotification;
import android.util.ArraySet;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
import java.util.Set;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconContainer.java
index 56f78f419275..065222762b33 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconContainer.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar;
import com.android.internal.statusbar.StatusBarIcon;
+
import java.util.ArrayList;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
index 3c52e8cab422..bc89889c48fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
@@ -27,16 +27,14 @@ import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.Rect;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
-
import android.widget.LinearLayout;
+
import com.android.internal.annotations.VisibleForTesting;
-import com.android.keyguard.AlphaOptimizedLinearLayout;
import com.android.settingslib.graph.SignalDrawable;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
index f3fc99e36426..045221f510fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
@@ -27,18 +27,14 @@ import android.content.res.ColorStateList;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
import android.widget.FrameLayout;
import android.widget.ImageView;
-
import android.widget.LinearLayout;
-import com.android.keyguard.AlphaOptimizedLinearLayout;
+
import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java
index f9afc7c34668..c4fadff16c09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java
@@ -16,12 +16,12 @@
package com.android.systemui.statusbar;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
import android.content.Context;
import android.content.DialogInterface;
import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
public class UserUtil {
public static void deleteUserWithPrompt(Context context, int userId,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
index 46f88635be79..bd328567fb46 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
@@ -3,10 +3,8 @@ package com.android.systemui.statusbar.car;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
import android.os.UserHandle;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
index 9ed092974963..81f7846b357d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
@@ -16,13 +16,10 @@
package com.android.systemui.statusbar.car;
-import android.app.UiModeManager;
import android.content.Context;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.View;
import android.widget.LinearLayout;
-import android.widget.TextView;
import com.android.keyguard.AlphaOptimizedImageButton;
import com.android.systemui.Dependency;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
index 0304086dbfda..f2923f7df248 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
@@ -1,5 +1,7 @@
package com.android.systemui.statusbar.car;
+import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
+
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadsetClient;
@@ -9,21 +11,19 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.telephony.SignalStrength;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.widget.ImageView;
+
import com.android.settingslib.graph.SignalDrawable;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.ScalingDrawableWrapper;
import com.android.systemui.statusbar.policy.BluetoothController;
-import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
-
/**
* Controller that monitors signal strength for a device that is connected via bluetooth.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java
index f9fa44b17489..0c91cba43390 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java
@@ -21,10 +21,10 @@ import android.content.Context;
import android.os.CountDownTimer;
import android.util.Log;
-import com.android.systemui.R;
-
import androidx.annotation.GuardedBy;
+import com.android.systemui.R;
+
/**
* Wrapper for a countdown timer that switches to Guest if the user has been driving with
* the keyguard up for configurable number of seconds.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index 53a7afe76d0d..d802ed8d6e3a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -29,7 +29,6 @@ import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.os.AsyncTask;
-import android.os.UserHandle;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -44,8 +43,8 @@ import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.util.UserIcons;
import com.android.systemui.R;
-
import com.android.systemui.statusbar.phone.SystemUIDialog;
+
import java.util.ArrayList;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
index 8c725446a3cb..6044a7e16b61 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
@@ -16,11 +16,7 @@
package com.android.systemui.statusbar.notification;
-import android.text.Layout;
-import android.text.TextUtils;
import android.util.Pools;
-import android.view.View;
-import android.widget.TextView;
/**
* A transform state of the action list
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java
index de4c3128e99f..dea1a07c0268 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/CustomInterpolatorTransformation.java
@@ -17,16 +17,11 @@
package com.android.systemui.statusbar.notification;
import android.view.View;
-import android.view.animation.Interpolator;
-import com.android.systemui.Interpolators;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.ViewTransformationHelper;
-import static com.android.systemui.statusbar.TransformableView.TRANSFORMING_VIEW_TITLE;
-import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
-
/**
* A custom transformation that modifies the interpolator
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java
index 454edbb1a037..f5a76f0499e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageGradientColorizer.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.notification;
import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
@@ -27,7 +26,6 @@ import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader;
-import android.graphics.Xfermode;
import android.graphics.drawable.Drawable;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
index 8c0d70062eb1..ab94008d656a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
@@ -23,9 +23,10 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
+import android.util.LayoutDirection;
+
import androidx.annotation.VisibleForTesting;
import androidx.palette.graphics.Palette;
-import android.util.LayoutDirection;
import com.android.internal.util.ContrastColorUtil;
import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java
index b97995dd5f93..a3fb2251f5aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingImageTransformState.java
@@ -20,7 +20,6 @@ import android.util.Pools;
import android.view.View;
import com.android.internal.widget.MessagingImageMessage;
-import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.ViewTransformationHelper;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
index 4e712a5054ea..da6d977f3f5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
@@ -114,8 +114,9 @@ public class NotificationData {
public CharSequence remoteInputText;
public List<SnoozeCriterion> snoozeCriteria;
public int userSentiment = Ranking.USER_SENTIMENT_NEUTRAL;
+ /** Smart Actions provided by the NotificationAssistantService. */
@NonNull
- public List<Notification.Action> smartActions = Collections.emptyList();
+ public List<Notification.Action> systemGeneratedSmartActions = Collections.emptyList();
public CharSequence[] smartReplies = new CharSequence[0];
private int mCachedContrastColor = COLOR_INVALID;
@@ -171,7 +172,7 @@ public class NotificationData {
importance = ranking.getImportance();
snoozeCriteria = ranking.getSnoozeCriteria();
userSentiment = ranking.getUserSentiment();
- smartActions = ranking.getSmartActions() == null
+ systemGeneratedSmartActions = ranking.getSmartActions() == null
? Collections.emptyList() : ranking.getSmartActions();
smartReplies = ranking.getSmartReplies() == null
? new CharSequence[0]
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 3bea7db14313..274d4b07b017 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -702,7 +702,6 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
&& !mPresenter.isPresenterFullyCollapsed();
row.setUseIncreasedCollapsedHeight(useIncreasedCollapsedHeight);
row.setUseIncreasedHeadsUpHeight(useIncreasedHeadsUp);
- row.setSmartActions(entry.smartActions);
row.setEntry(entry);
row.updateInflationFlag(FLAG_CONTENT_VIEW_HEADS_UP, shouldHeadsUp(entry));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
index 07b8c3558304..337f31295308 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java
@@ -29,9 +29,9 @@ import com.android.internal.widget.ViewClippingUtil;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.ViewTransformationHelper;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
/**
* A transform state of a view.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
index da8954ae4c03..75613a42eb5e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
@@ -16,9 +16,10 @@
package com.android.systemui.statusbar.notification;
-import androidx.collection.ArraySet;
import android.view.View;
+import androidx.collection.ArraySet;
+
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
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 5166e061c3ef..c7876cf43026 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
@@ -39,7 +39,6 @@ import android.animation.ObjectAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.Notification;
import android.app.NotificationChannel;
import android.content.Context;
import android.content.pm.PackageInfo;
@@ -1567,10 +1566,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mNotificationInflater.setUsesIncreasedHeight(use);
}
- public void setSmartActions(List<Notification.Action> smartActions) {
- mNotificationInflater.setSmartActions(smartActions);
- }
-
public void setUseIncreasedHeadsUpHeight(boolean use) {
mUseIncreasedHeadsUpHeight = use;
mNotificationInflater.setUsesIncreasedHeadsUpHeight(use);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
index 1a4ef0914664..16796dd86e18 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
@@ -16,10 +16,13 @@
package com.android.systemui.statusbar.notification.row;
+import static android.service.notification.NotificationListenerService.Ranking
+ .USER_SENTIMENT_NEGATIVE;
+
import android.content.Context;
+import android.util.Log;
import androidx.annotation.VisibleForTesting;
-import android.util.Log;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Dependency;
@@ -31,8 +34,6 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
-
/**
* Manager for the notification blocking helper - tracks and helps create the blocking helper
* affordance.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index b838c9b5482d..37bf06edde4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -21,6 +21,8 @@ import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.service.notification.NotificationListenerService.Ranking
.USER_SENTIMENT_NEGATIVE;
+import static com.android.systemui.statusbar.notification.row.NotificationInfo.ACTION_NONE;
+
import android.app.INotificationManager;
import android.app.NotificationChannel;
import android.content.Context;
@@ -189,7 +191,13 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
} else if (gutsView instanceof AppOpsInfo) {
initializeAppOpsInfo(row, (AppOpsInfo) gutsView);
} else if (gutsView instanceof NotificationInfo) {
- initializeNotificationInfo(row, (NotificationInfo) gutsView);
+ int action;
+ if (item instanceof NotificationMenuRow.NotificationInfoMenuItem) {
+ action = ((NotificationMenuRow.NotificationInfoMenuItem) item).mAction;
+ } else {
+ action = ACTION_NONE;
+ }
+ initializeNotificationInfo(row, (NotificationInfo) gutsView, action);
}
return true;
} catch (Exception e) {
@@ -246,14 +254,15 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
/**
* Sets up the {@link NotificationInfo} inside the notification row's guts.
- *
* @param row view to set up the guts for
* @param notificationInfoView view to set up/bind within {@code row}
+ * @param action The action to take immediately upon binding, if any.
*/
@VisibleForTesting
void initializeNotificationInfo(
final ExpandableNotificationRow row,
- NotificationInfo notificationInfoView) throws Exception {
+ NotificationInfo notificationInfoView,
+ @NotificationInfo.NotificationInfoAction int action) throws Exception {
NotificationGuts guts = row.getGuts();
StatusBarNotification sbn = row.getStatusBarNotification();
String packageName = sbn.getPackageName();
@@ -297,7 +306,8 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
isForBlockingHelper,
row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE,
row.getEntry().noisy,
- row.getEntry().importance);
+ row.getEntry().importance,
+ action);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java
index 38d6b3593be2..e1c2f7359ce3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInflater.java
@@ -43,10 +43,7 @@ import com.android.systemui.util.Assert;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
-import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
@@ -131,7 +128,6 @@ public class NotificationInflater {
private boolean mIsChildInGroup;
private InflationCallback mCallback;
private boolean mRedactAmbient;
- private List<Notification.Action> mSmartActions;
private final ArrayMap<Integer, RemoteViews> mCachedContentViews = new ArrayMap<>();
public NotificationInflater(ExpandableNotificationRow row) {
@@ -161,10 +157,6 @@ public class NotificationInflater {
mUsesIncreasedHeight = usesIncreasedHeight;
}
- public void setSmartActions(List<Notification.Action> smartActions) {
- mSmartActions = smartActions;
- }
-
public void setUsesIncreasedHeadsUpHeight(boolean usesIncreasedHeight) {
mUsesIncreasedHeadsUpHeight = usesIncreasedHeight;
}
@@ -258,8 +250,7 @@ public class NotificationInflater {
StatusBarNotification sbn = mRow.getEntry().notification;
AsyncInflationTask task = new AsyncInflationTask(sbn, reInflateFlags, mCachedContentViews,
mRow, mIsLowPriority, mIsChildInGroup, mUsesIncreasedHeight,
- mUsesIncreasedHeadsUpHeight, mRedactAmbient, mCallback, mRemoteViewClickHandler,
- mSmartActions);
+ mUsesIncreasedHeadsUpHeight, mRedactAmbient, mCallback, mRemoteViewClickHandler);
if (mCallback != null && mCallback.doInflateSynchronous()) {
task.onPostExecute(task.doInBackground());
} else {
@@ -765,15 +756,13 @@ public class NotificationInflater {
private Exception mError;
private RemoteViews.OnClickHandler mRemoteViewClickHandler;
private CancellationSignal mCancellationSignal;
- private List<Notification.Action> mSmartActions;
private AsyncInflationTask(StatusBarNotification notification,
@InflationFlag int reInflateFlags,
ArrayMap<Integer, RemoteViews> cachedContentViews, ExpandableNotificationRow row,
boolean isLowPriority, boolean isChildInGroup, boolean usesIncreasedHeight,
boolean usesIncreasedHeadsUpHeight, boolean redactAmbient,
- InflationCallback callback, RemoteViews.OnClickHandler remoteViewClickHandler,
- List<Notification.Action> smartActions) {
+ InflationCallback callback, RemoteViews.OnClickHandler remoteViewClickHandler) {
mRow = row;
mSbn = notification;
mReInflateFlags = reInflateFlags;
@@ -786,9 +775,6 @@ public class NotificationInflater {
mRedactAmbient = redactAmbient;
mRemoteViewClickHandler = remoteViewClickHandler;
mCallback = callback;
- mSmartActions = smartActions == null
- ? Collections.emptyList()
- : new ArrayList<>(smartActions);
NotificationData.Entry entry = row.getEntry();
entry.setInflationTask(this);
}
@@ -806,8 +792,6 @@ public class NotificationInflater {
= Notification.Builder.recoverBuilder(mContext,
mSbn.getNotification());
- applyChanges(recoveredBuilder);
-
Context packageContext = mSbn.getPackageContext(mContext);
Notification notification = mSbn.getNotification();
if (notification.isMediaNotification()) {
@@ -834,18 +818,6 @@ public class NotificationInflater {
}
}
- /**
- * Apply changes to the given notification builder, like adding smart actions suggested by
- * a {@link android.service.notification.NotificationAssistantService}.
- */
- private void applyChanges(Notification.Builder builder) {
- if (mSmartActions != null) {
- for (Notification.Action smartAction : mSmartActions) {
- builder.addAction(smartAction);
- }
- }
- }
-
private void handleError(Exception e) {
mRow.getEntry().onInflationTaskFinished();
StatusBarNotification sbn = mRow.getStatusBarNotification();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 522da4d51470..3a7091bb843a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -71,16 +71,19 @@ import java.util.List;
public class NotificationInfo extends LinearLayout implements NotificationGuts.GutsContent {
private static final String TAG = "InfoGuts";
- @IntDef(prefix = { "SWAP_CONTENT_" }, value = {
- SWAP_CONTENT_UNDO,
- SWAP_CONTENT_TOGGLE_SILENT,
- SWAP_CONTENT_BLOCK,
+ @IntDef(prefix = { "ACTION_" }, value = {
+ ACTION_NONE,
+ ACTION_UNDO,
+ ACTION_TOGGLE_SILENT,
+ ACTION_BLOCK,
})
- @interface SwapContentAction {}
+ public @interface NotificationInfoAction {
+ }
- private static final int SWAP_CONTENT_UNDO = 0;
- private static final int SWAP_CONTENT_TOGGLE_SILENT = 1;
- private static final int SWAP_CONTENT_BLOCK = 2;
+ public static final int ACTION_NONE = 0;
+ public static final int ACTION_UNDO = 1;
+ public static final int ACTION_TOGGLE_SILENT = 2;
+ public static final int ACTION_BLOCK = 3;
private INotificationManager mINotificationManager;
private PackageManager mPm;
@@ -123,8 +126,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
private OnClickListener mOnToggleSilent = v -> {
Runnable saveImportance = () -> {
- mExitReason = NotificationCounters.BLOCKING_HELPER_TOGGLE_SILENT;
- swapContent(SWAP_CONTENT_TOGGLE_SILENT);
+ swapContent(ACTION_TOGGLE_SILENT, true /* animate */);
};
if (mCheckSaveListener != null) {
mCheckSaveListener.checkSave(saveImportance, mSbn);
@@ -135,8 +137,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
private OnClickListener mOnStopOrMinimizeNotifications = v -> {
Runnable saveImportance = () -> {
- mExitReason = NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS;
- swapContent(SWAP_CONTENT_BLOCK);
+ swapContent(ACTION_BLOCK, true /* animate */);
};
if (mCheckSaveListener != null) {
mCheckSaveListener.checkSave(saveImportance, mSbn);
@@ -149,7 +150,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
// Reset exit counter that we'll log and record an undo event separately (not an exit event)
mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_UNDO);
- swapContent(SWAP_CONTENT_UNDO);
+ swapContent(ACTION_UNDO, true /* animate */);
};
public NotificationInfo(Context context, AttributeSet attrs) {
@@ -185,13 +186,14 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
boolean isDeviceProvisioned,
boolean isNonblockable,
boolean isNoisy,
- int importance)
+ int importance,
+ @NotificationInfoAction int action)
throws RemoteException {
bindNotification(pm, iNotificationManager, pkg, notificationChannel,
numUniqueChannelsInRow, sbn, checkSaveListener, onSettingsClick,
onAppSettingsClick, isDeviceProvisioned, isNonblockable,
false /* isBlockingHelper */, false /* isUserSentimentNegative */, isNoisy,
- importance);
+ importance, action);
}
public void bindNotification(
@@ -209,7 +211,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
boolean isForBlockingHelper,
boolean isUserSentimentNegative,
boolean isNoisy,
- int importance)
+ int importance,
+ @NotificationInfoAction int action)
throws RemoteException {
mINotificationManager = iNotificationManager;
mMetricsLogger = Dependency.get(MetricsLogger.class);
@@ -250,6 +253,10 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
bindHeader();
bindPrompt();
bindButtons();
+
+ if (action != ACTION_NONE) {
+ swapContent(action, false /* don't animate */);
+ }
}
private void bindHeader() throws RemoteException {
@@ -351,7 +358,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
}
private void saveImportance() {
- if (!mIsNonblockable) {
+ if (!mIsNonblockable
+ || mExitReason != NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS) {
updateImportance();
}
}
@@ -421,7 +429,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
}
}
- private void swapContent(@SwapContentAction int action) {
+ private void swapContent(@NotificationInfoAction int action, boolean animate) {
if (mExpandAnimation != null) {
mExpandAnimation.cancel();
}
@@ -432,10 +440,11 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
View header = findViewById(R.id.header);
switch (action) {
- case SWAP_CONTENT_UNDO:
+ case ACTION_UNDO:
mChosenImportance = mStartingChannelImportance;
break;
- case SWAP_CONTENT_TOGGLE_SILENT:
+ case ACTION_TOGGLE_SILENT:
+ mExitReason = NotificationCounters.BLOCKING_HELPER_TOGGLE_SILENT;
if (mStartingChannelOrNotificationImportance >= IMPORTANCE_DEFAULT) {
mChosenImportance = IMPORTANCE_LOW;
confirmationText.setText(R.string.notification_channel_silenced);
@@ -444,7 +453,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
confirmationText.setText(R.string.notification_channel_unsilenced);
}
break;
- case SWAP_CONTENT_BLOCK:
+ case ACTION_BLOCK:
+ mExitReason = NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS;
if (mIsForeground) {
mChosenImportance = IMPORTANCE_MIN;
confirmationText.setText(R.string.notification_channel_minimized);
@@ -457,38 +467,41 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
throw new IllegalArgumentException();
}
- boolean isUndo = action == SWAP_CONTENT_UNDO;
- ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
- prompt.getAlpha(), isUndo ? 1f : 0f);
- promptAnim.setInterpolator(isUndo ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
- ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
- confirmation.getAlpha(), isUndo ? 0f : 1f);
- confirmAnim.setInterpolator(isUndo ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
+ boolean isUndo = action == ACTION_UNDO;
prompt.setVisibility(isUndo ? VISIBLE : GONE);
confirmation.setVisibility(isUndo ? GONE : VISIBLE);
header.setVisibility(isUndo ? VISIBLE : GONE);
- mExpandAnimation = new AnimatorSet();
- mExpandAnimation.playTogether(promptAnim, confirmAnim);
- mExpandAnimation.setDuration(150);
- mExpandAnimation.addListener(new AnimatorListenerAdapter() {
- boolean cancelled = false;
-
- @Override
- public void onAnimationCancel(Animator animation) {
- cancelled = true;
- }
+ if (animate) {
+ ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
+ prompt.getAlpha(), isUndo ? 1f : 0f);
+ promptAnim.setInterpolator(isUndo ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
+ ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
+ confirmation.getAlpha(), isUndo ? 0f : 1f);
+ confirmAnim.setInterpolator(isUndo ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
+
+ mExpandAnimation = new AnimatorSet();
+ mExpandAnimation.playTogether(promptAnim, confirmAnim);
+ mExpandAnimation.setDuration(150);
+ mExpandAnimation.addListener(new AnimatorListenerAdapter() {
+ boolean mCancelled = false;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCancelled = true;
+ }
- @Override
- public void onAnimationEnd(Animator animation) {
- if (!cancelled) {
- prompt.setVisibility(isUndo ? VISIBLE : GONE);
- confirmation.setVisibility(isUndo ? GONE : VISIBLE);
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!mCancelled) {
+ prompt.setVisibility(isUndo ? VISIBLE : GONE);
+ confirmation.setVisibility(isUndo ? GONE : VISIBLE);
+ }
}
- }
- });
- mExpandAnimation.start();
+ });
+ mExpandAnimation.start();
+ }
// Since we're swapping/update the content, reset the timeout so the UI can't close
// immediately after the update.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index 674c8ee3f35c..c16b28fbab9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -17,12 +17,16 @@
package com.android.systemui.statusbar.notification.row;
import static com.android.systemui.SwipeHelper.SWIPED_FAR_ENOUGH_SIZE_FRACTION;
+import static com.android.systemui.statusbar.notification.row.NotificationInfo.ACTION_BLOCK;
+import static com.android.systemui.statusbar.notification.row.NotificationInfo.ACTION_NONE;
+import static com.android.systemui.statusbar.notification.row.NotificationInfo.ACTION_TOGGLE_SILENT;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
import android.app.Notification;
+import android.app.NotificationManager;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
@@ -40,7 +44,9 @@ import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.AlphaOptimizedImageView;
+import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.row.NotificationGuts.GutsContent;
+import com.android.systemui.statusbar.notification.row.NotificationInfo.NotificationInfoAction;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import java.util.ArrayList;
@@ -67,7 +73,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
private Context mContext;
private FrameLayout mMenuContainer;
- private MenuItem mInfoItem;
+ private NotificationInfoMenuItem mInfoItem;
private MenuItem mAppOpsItem;
private MenuItem mSnoozeItem;
private ArrayList<MenuItem> mLeftMenuItems;
@@ -170,7 +176,9 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
@Override
public void createMenu(ViewGroup parent, StatusBarNotification sbn) {
mParent = (ExpandableNotificationRow) parent;
- createMenuViews(true /* resetState */);
+ createMenuViews(true /* resetState */,
+ sbn != null && (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE)
+ != 0);
}
@Override
@@ -214,7 +222,8 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
// Menu hasn't been created yet, no need to do anything.
return;
}
- createMenuViews(!isMenuVisible() /* resetState */);
+ createMenuViews(!isMenuVisible() /* resetState */,
+ (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0);
}
@Override
@@ -229,30 +238,47 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
mParent.removeListener();
}
- private void createMenuViews(boolean resetState) {
+ private void createMenuViews(boolean resetState, final boolean isForeground) {
final Resources res = mContext.getResources();
mHorizSpaceForIcon = res.getDimensionPixelSize(R.dimen.notification_menu_icon_size);
mVertSpaceForIcons = res.getDimensionPixelSize(R.dimen.notification_min_height);
mLeftMenuItems.clear();
mRightMenuItems.clear();
// Construct the menu items based on the notification
- if (mParent != null && mParent.getStatusBarNotification() != null) {
- int flags = mParent.getStatusBarNotification().getNotification().flags;
- boolean isForeground = (flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
- if (!isForeground) {
- // Only show snooze for non-foreground notifications
- mSnoozeItem = createSnoozeItem(mContext);
- mLeftMenuItems.add(mSnoozeItem);
- mRightMenuItems.add(mSnoozeItem);
- }
+ if (!isForeground) {
+ // Only show snooze for non-foreground notifications
+ mSnoozeItem = createSnoozeItem(mContext);
+ mLeftMenuItems.add(mSnoozeItem);
}
mInfoItem = createInfoItem(mContext);
- mLeftMenuItems.add(mInfoItem);
- mRightMenuItems.add(mInfoItem);
+ if (!NotificationUtils.useNewInterruptionModel(mContext)) {
+ mLeftMenuItems.add(mInfoItem);
+ }
mAppOpsItem = createAppOpsItem(mContext);
mLeftMenuItems.add(mAppOpsItem);
- mRightMenuItems.add(mAppOpsItem);
+
+ if (NotificationUtils.useNewInterruptionModel(mContext)) {
+ if (!mParent.getIsNonblockable()) {
+ mRightMenuItems.add(createBlockItem(mContext, mInfoItem.getGutsView()));
+ }
+ // TODO(kprevas): this is duplicated logic
+ // but it's currently spread across NotificationGutsManager and NotificationInfo.
+ // Try to consolidate and reuse here.
+ boolean canToggleSilent = !mParent.getIsNonblockable()
+ && !isForeground
+ && mParent.getEntry().noisy;
+ if (canToggleSilent) {
+ int channelImportance = mParent.getEntry().channel.getImportance();
+ int effectiveImportance =
+ channelImportance == NotificationManager.IMPORTANCE_UNSPECIFIED
+ ? mParent.getEntry().importance : channelImportance;
+ mRightMenuItems.add(createToggleSilentItem(mContext, mInfoItem.getGutsView(),
+ effectiveImportance < NotificationManager.IMPORTANCE_DEFAULT));
+ }
+ } else {
+ mRightMenuItems.addAll(mLeftMenuItems);
+ }
populateMenuViews();
if (resetState) {
@@ -595,7 +621,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
// TODO -- handle / allow custom menu items!
}
- public static MenuItem createSnoozeItem(Context context) {
+ static MenuItem createSnoozeItem(Context context) {
Resources res = context.getResources();
NotificationSnooze content = (NotificationSnooze) LayoutInflater.from(context)
.inflate(R.layout.notification_snooze, null, false);
@@ -605,17 +631,16 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
return snooze;
}
- public static MenuItem createInfoItem(Context context) {
+ static NotificationInfoMenuItem createInfoItem(Context context) {
Resources res = context.getResources();
String infoDescription = res.getString(R.string.notification_menu_gear_description);
NotificationInfo infoContent = (NotificationInfo) LayoutInflater.from(context).inflate(
R.layout.notification_info, null, false);
- MenuItem info = new NotificationMenuItem(context, infoDescription, infoContent,
- R.drawable.ic_settings);
- return info;
+ return new NotificationInfoMenuItem(context, infoDescription, infoContent,
+ R.drawable.ic_settings, ACTION_NONE);
}
- public static MenuItem createAppOpsItem(Context context) {
+ static MenuItem createAppOpsItem(Context context) {
AppOpsInfo appOpsContent = (AppOpsInfo) LayoutInflater.from(context).inflate(
R.layout.app_ops_info, null, false);
MenuItem info = new NotificationMenuItem(context, null, appOpsContent,
@@ -623,6 +648,29 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
return info;
}
+ private static MenuItem createBlockItem(Context context, NotificationInfo gutsView) {
+ return new NotificationInfoMenuItem(
+ context,
+ context.getResources().getString(R.string.inline_stop_button),
+ gutsView,
+ R.drawable.ic_notification_block,
+ ACTION_BLOCK);
+ }
+
+ private static MenuItem createToggleSilentItem(Context context, NotificationInfo gutsView,
+ boolean isCurrentlySilent) {
+ return new NotificationInfoMenuItem(
+ context,
+ isCurrentlySilent
+ ? context.getResources().getString(R.string.inline_silent_button_alert)
+ : context.getResources().getString(R.string.inline_silent_button_silent),
+ gutsView,
+ isCurrentlySilent
+ ? R.drawable.ic_notifications_alert
+ : R.drawable.ic_notifications_silence,
+ ACTION_TOGGLE_SILENT);
+ }
+
private void addMenuView(MenuItem item, ViewGroup parent) {
View menuView = item.getMenuView();
if (menuView != null) {
@@ -704,7 +752,8 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
* Add a new 'guts' panel. If iconResId < 0 it will not appear in the slow swipe menu
* but can still be exposed via other affordances.
*/
- public NotificationMenuItem(Context context, String s, GutsContent content, int iconResId) {
+ public NotificationMenuItem(Context context, String contentDescription, GutsContent content,
+ int iconResId) {
Resources res = context.getResources();
int padding = res.getDimensionPixelSize(R.dimen.notification_menu_icon_padding);
int tint = res.getColor(R.color.notification_gear_color);
@@ -717,7 +766,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
iv.setAlpha(1f);
mMenuView = iv;
}
- mContentDescription = s;
+ mContentDescription = contentDescription;
mGutsContent = content;
}
@@ -737,4 +786,23 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
return mContentDescription;
}
}
+
+ /** A {@link NotificationMenuItem} with an associated {@link NotificationInfoAction}. */
+ public static class NotificationInfoMenuItem extends NotificationMenuItem {
+
+ @NotificationInfoAction
+ int mAction;
+
+ public NotificationInfoMenuItem(Context context, String contentDescription,
+ NotificationInfo content, int iconResId,
+ @NotificationInfoAction int action) {
+ super(context, contentDescription, content, iconResId);
+ this.mAction = action;
+ }
+
+ @Override
+ public NotificationInfo getGutsView() {
+ return (NotificationInfo) super.getGutsView();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
index 75b05c26886d..d65f2c53598c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java
@@ -16,16 +16,6 @@
package com.android.systemui.statusbar.notification.row;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
-
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -53,8 +43,17 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
public class NotificationSnooze extends LinearLayout
implements NotificationGuts.GutsContent, View.OnClickListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
index a21794bc4835..1741a0b6b37c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowInflaterTask.java
@@ -17,11 +17,12 @@
package com.android.systemui.statusbar.notification.row;
import android.content.Context;
-import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
+import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
+
import com.android.systemui.R;
import com.android.systemui.statusbar.InflationTask;
import com.android.systemui.statusbar.notification.NotificationData;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
index 8a061a606099..1b40c06a5867 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/StackScrollerDecorView.java
@@ -24,7 +24,6 @@ import android.view.animation.Interpolator;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Interpolators;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
/**
* A common base class for all views in the notification stack scroller which don't have a
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
index 133df3c154de..4261df3dab27 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationBigTextTemplateViewWrapper.java
@@ -21,8 +21,8 @@ import android.service.notification.StatusBarNotification;
import android.view.View;
import com.android.internal.widget.ImageFloatingTextView;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
/**
* Wraps a notification containing a big text template
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 6ca07ed8b161..1be2afe744a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -16,9 +16,9 @@
package com.android.systemui.statusbar.notification.row.wrapper;
+import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
import static com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
.DEFAULT_HEADER_VISIBLE_AMOUNT;
-import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
import android.app.Notification;
import android.content.Context;
@@ -34,12 +34,13 @@ import android.widget.TextView;
import com.android.internal.widget.NotificationExpandButton;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.ViewTransformationHelper;
import com.android.systemui.statusbar.notification.CustomInterpolatorTransformation;
import com.android.systemui.statusbar.notification.ImageTransformState;
+import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.TransformState;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.TransformableView;
-import com.android.systemui.statusbar.ViewTransformationHelper;
import java.util.Stack;
@@ -69,7 +70,8 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
super(ctx, view, row);
mShowExpandButtonAtEnd = ctx.getResources().getBoolean(
- R.bool.config_showNotificationExpandButtonAtEnd);
+ R.bool.config_showNotificationExpandButtonAtEnd)
+ || NotificationUtils.useNewInterruptionModel(ctx);
mTransformationHelper = new ViewTransformationHelper();
// we want to avoid that the header clashes with the other text when transforming
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
index 37d2f6bba7ff..5a9a56865a5c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -19,8 +19,8 @@ package com.android.systemui.statusbar.notification.row.wrapper;
import android.content.Context;
import android.view.View;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
/**
* Wraps a notification containing a media template
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java
index 13c596023f95..c9a274294d16 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMessagingTemplateViewWrapper.java
@@ -16,15 +16,15 @@
package com.android.systemui.statusbar.notification.row.wrapper;
+import android.content.Context;
+import android.view.View;
+
import com.android.internal.widget.MessagingLayout;
import com.android.internal.widget.MessagingLinearLayout;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import android.content.Context;
-import android.view.View;
-
/**
* Wraps a notification containing a messaging template
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
index d934902b96e8..ff5e15bfe751 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
@@ -37,11 +37,11 @@ import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.statusbar.CrossFadeHelper;
+import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.ViewTransformationHelper;
import com.android.systemui.statusbar.notification.ImageTransformState;
import com.android.systemui.statusbar.notification.TransformState;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.TransformableView;
-import com.android.systemui.statusbar.ViewTransformationHelper;
import com.android.systemui.statusbar.notification.row.HybridNotificationView;
/**
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 f76284dd1ffc..1efdc56874f3 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
@@ -24,9 +24,9 @@ import android.view.NotificationHeaderView;
import android.view.View;
import com.android.systemui.statusbar.CrossFadeHelper;
+import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.notification.TransformState;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.TransformableView;
/**
* Wraps the actual notification content view; used to implement behaviors which are different for
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
index c6f953c8a6ae..ba56a943f559 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
@@ -16,10 +16,11 @@
package com.android.systemui.statusbar.notification.stack;
-import androidx.collection.ArraySet;
import android.util.Property;
import android.view.View;
+import androidx.collection.ArraySet;
+
import java.util.ArrayList;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index da089b307850..74b4aa2a7057 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -33,13 +33,13 @@ import android.widget.TextView;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.NotificationHeaderUtil;
+import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.HybridGroupManager;
import com.android.systemui.statusbar.notification.row.HybridNotificationView;
-import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
import java.util.ArrayList;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
index cfb6d990a9a7..4d100a46c48a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
@@ -16,17 +16,18 @@
package com.android.systemui.statusbar.notification.stack;
-import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
+import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator
+ .ExpandAnimationParameters;
import android.view.View;
import android.view.ViewGroup;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
/**
* Interface representing the entity that contains notifications. It can have
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 7bd582031e4a..ff31b261eb85 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -401,6 +401,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
*/
private float mBackgroundXFactor = 1f;
+ private boolean mSwipingInProgress;
+
private boolean mUsingLightTheme;
private boolean mQsExpanded;
private boolean mForwardScrollable;
@@ -3286,7 +3288,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
|| ev.getActionMasked() == MotionEvent.ACTION_UP;
handleEmptySpaceClick(ev);
boolean expandWantsIt = false;
- boolean swipingInProgress = mSwipeHelper.isSwipingInProgress();
+ boolean swipingInProgress = mSwipingInProgress;
if (mIsExpanded && !swipingInProgress && !mOnlyScrollingInThisMotion) {
if (isCancelOrUp) {
mExpandHelper.onlyObserveMovements(false);
@@ -3341,7 +3343,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@Override
@ShadeViewRefactor(RefactorComponent.INPUT)
public boolean onGenericMotionEvent(MotionEvent event) {
- if (!isScrollingEnabled() || !mIsExpanded || mSwipeHelper.isSwipingInProgress() || mExpandingNotification
+ if (!isScrollingEnabled() || !mIsExpanded || mSwipingInProgress || mExpandingNotification
|| mDisallowScrollingInThisMotion) {
return false;
}
@@ -3568,7 +3570,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
initDownStates(ev);
handleEmptySpaceClick(ev);
boolean expandWantsIt = false;
- boolean swipingInProgress = mSwipeHelper.isSwipingInProgress();
+ boolean swipingInProgress = mSwipingInProgress;
if (!swipingInProgress && !mOnlyScrollingInThisMotion) {
expandWantsIt = mExpandHelper.onInterceptTouchEvent(ev);
}
@@ -3847,6 +3849,14 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
}
+ @ShadeViewRefactor(RefactorComponent.INPUT)
+ private void setSwipingInProgress(boolean swiping) {
+ mSwipingInProgress = swiping;
+ if (swiping) {
+ requestDisallowInterceptTouchEvent(true);
+ }
+ }
+
@Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void onWindowFocusChanged(boolean hasWindowFocus) {
@@ -5642,6 +5652,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@Override
public void onDragCancelled(View v) {
+ setSwipingInProgress(false);
mFalsingManager.onNotificatonStopDismissing();
}
@@ -5669,6 +5680,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
*/
public void handleChildViewDismissed(View view) {
+ setSwipingInProgress(false);
if (mDismissAllInProgress) {
return;
}
@@ -5737,6 +5749,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@Override
public void onBeginDrag(View v) {
mFalsingManager.onNotificatonStartDismissing();
+ setSwipingInProgress(true);
mAmbientState.onBeginDrag(v);
updateContinuousShadowDrawing();
if (mAnimationsEnabled && (mIsExpanded || !isPinnedHeadsUp(v))) {
@@ -5786,7 +5799,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@Override
public boolean canChildBeDismissedInDirection(View v, boolean isRightOrDown) {
- return (isLayoutRtl() ? !isRightOrDown : isRightOrDown) && canChildBeDismissed(v);
+ boolean isValidDirection;
+ if (NotificationUtils.useNewInterruptionModel(mContext)) {
+ isValidDirection = isLayoutRtl() ? !isRightOrDown : isRightOrDown;
+ } else {
+ isValidDirection = true;
+ }
+ return isValidDirection && canChildBeDismissed(v);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index 599da3b280be..f1d9549b9284 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -165,15 +165,15 @@ class NotificationSwipeHelper extends SwipeHelper
if (menuRow.isSnappedAndOnSameSide()) {
// Menu was snapped to previously and we're on the same side
- handleSwipeFromSnap(ev, animView, velocity, menuRow);
+ handleSwipeFromOpenState(ev, animView, velocity, menuRow);
} else {
// Menu has not been snapped, or was snapped previously but is now on
// the opposite side.
- handleSwipeFromNonSnap(ev, animView, velocity, menuRow);
+ handleSwipeFromClosedState(ev, animView, velocity, menuRow);
}
}
- private void handleSwipeFromNonSnap(MotionEvent ev, View animView, float velocity,
+ private void handleSwipeFromClosedState(MotionEvent ev, View animView, float velocity,
NotificationMenuRowPlugin menuRow) {
boolean isDismissGesture = isDismissGesture(ev);
final boolean gestureTowardsMenu = menuRow.isTowardsMenu(velocity);
@@ -183,10 +183,14 @@ class NotificationSwipeHelper extends SwipeHelper
final boolean showMenuForSlowOnGoing = !menuRow.canBeDismissed()
&& timeForGesture >= SWIPE_MENU_TIMING;
- if (!isFalseGesture(ev)
- && (swipedEnoughToShowMenu(menuRow)
- && (!gestureFastEnough || showMenuForSlowOnGoing))
- || (gestureTowardsMenu && !isDismissGesture)) {
+ boolean isNonDismissGestureTowardsMenu = gestureTowardsMenu && !isDismissGesture;
+ boolean isSlowSwipe = !gestureFastEnough || showMenuForSlowOnGoing;
+ boolean slowSwipedFarEnough = swipedEnoughToShowMenu(menuRow) && isSlowSwipe;
+ boolean isFastNonDismissGesture =
+ gestureFastEnough && !gestureTowardsMenu && !isDismissGesture;
+ boolean isMenuRevealingGestureAwayFromMenu = slowSwipedFarEnough || isFastNonDismissGesture;
+ if (isNonDismissGestureTowardsMenu
+ || (!isFalseGesture(ev) && isMenuRevealingGestureAwayFromMenu)) {
// Menu has not been snapped to previously and this is menu revealing gesture
snapOpen(animView, menuRow.getMenuSnapTarget(), velocity);
menuRow.onSnapOpen();
@@ -199,7 +203,7 @@ class NotificationSwipeHelper extends SwipeHelper
}
}
- private void handleSwipeFromSnap(MotionEvent ev, View animView, float velocity,
+ private void handleSwipeFromOpenState(MotionEvent ev, View animView, float velocity,
NotificationMenuRowPlugin menuRow) {
boolean isDismissGesture = isDismissGesture(ev);
@@ -227,7 +231,6 @@ class NotificationSwipeHelper extends SwipeHelper
if (mCallback.isExpanded()) {
// We don't want to quick-dismiss when it's a heads up as this might lead to closing
// of the panel early.
- mSwipingInProgress = false;
mCallback.handleChildViewDismissed(view);
}
mCallback.onDismiss();
@@ -247,7 +250,6 @@ class NotificationSwipeHelper extends SwipeHelper
@Override
public void snapChild(final View animView, final float targetLeft, float velocity) {
superSnapChild(animView, targetLeft, velocity);
- mSwipingInProgress = false;
mCallback.onDragCancelled(animView);
if (targetLeft == 0) {
handleMenuCoveredOrDismissed();
@@ -354,7 +356,6 @@ class NotificationSwipeHelper extends SwipeHelper
public void onMenuShown(View animView) {
setExposedMenuView(getTranslatingParentView());
- mSwipingInProgress = false;
mCallback.onDragCancelled(animView);
Handler handler = getHandler();
@@ -422,4 +423,4 @@ class NotificationSwipeHelper extends SwipeHelper
void onDismiss();
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index da3fb66ec1db..a94401b6319c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -26,10 +26,10 @@ import android.view.animation.Interpolator;
import com.android.keyguard.KeyguardSliceView;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
import java.util.ArrayList;
import java.util.HashSet;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
index a15fd7083017..b00068cd2445 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
@@ -28,9 +28,9 @@ import android.view.animation.Interpolator;
import com.android.systemui.Dumpable;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.policy.HeadsUpUtil;
import java.io.FileDescriptor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index ab58660f6ed6..1d7e899afc10 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -15,8 +15,10 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
+import android.hardware.display.ColorDisplayManager;
import android.os.Handler;
import android.provider.Settings.Secure;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ColorDisplayController;
import com.android.systemui.Dependency;
@@ -80,7 +82,7 @@ public class AutoTileManager {
Dependency.get(ManagedProfileController.class).addCallback(mProfileCallback);
}
if (!mAutoTracker.isAdded(NIGHT)
- && ColorDisplayController.isAvailable(mContext)) {
+ && ColorDisplayManager.isNightDisplayAvailable(mContext)) {
Dependency.get(ColorDisplayController.class).setListener(mColorDisplayCallback);
}
}
@@ -93,7 +95,9 @@ public class AutoTileManager {
Dependency.get(HotspotController.class).removeCallback(mHotspotCallback);
Dependency.get(DataSaverController.class).removeCallback(mDataSaverListener);
Dependency.get(ManagedProfileController.class).removeCallback(mProfileCallback);
- Dependency.get(ColorDisplayController.class).setListener(null);
+ if (ColorDisplayManager.isNightDisplayAvailable(mContext)) {
+ Dependency.get(ColorDisplayController.class).setListener(null);
+ }
}
public void unmarkTileAsAutoAdded(String tabSpec) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
index c32dcea1f646..3d814732a2e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.phone;
-import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
@@ -25,9 +24,9 @@ import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
+import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
-import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.os.SystemClock;
import android.util.Log;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 8325bf8085bd..302d630eeb2b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -16,18 +16,18 @@
package com.android.systemui.statusbar.phone;
-import android.hardware.biometrics.BiometricSourceType;
import android.content.Context;
+import android.hardware.biometrics.BiometricSourceType;
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.Trace;
import android.util.Log;
+import com.android.internal.util.LatencyTracker;
import com.android.keyguard.KeyguardConstants;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.internal.util.LatencyTracker;
import com.android.systemui.Dependency;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index 119f01adddf8..4ced702f479e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -21,8 +21,8 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.view.View;
-
import android.view.View.AccessibilityDelegate;
+
import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
index 970304399b67..cc8adde2ed04 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.phone;
import android.annotation.IdRes;
import android.annotation.NonNull;
import android.view.View;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index e052e531ddd2..3425dd237430 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -24,20 +24,20 @@ import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.DemoMode;
import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarMobileView;
import com.android.systemui.statusbar.StatusBarWifiView;
+import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
+
import java.util.ArrayList;
public class DemoStatusIcons extends StatusIconContainer implements DemoMode, DarkReceiver {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
index 8f49c85b0938..efc289185cfa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandableIndicator.java
@@ -18,6 +18,7 @@ import android.content.Context;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.util.AttributeSet;
import android.widget.ImageView;
+
import com.android.systemui.R;
public class ExpandableIndicator extends ImageView {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index c66bbb1696ac..40f9f45bf8bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -26,12 +26,12 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.HeadsUpStatusBarView;
import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 976327a49f58..d05893d55508 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -21,8 +21,6 @@ import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
-import androidx.collection.ArraySet;
-
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.Region.Op;
@@ -33,16 +31,18 @@ import android.view.Gravity;
import android.view.View;
import android.view.ViewTreeObserver;
+import androidx.collection.ArraySet;
+
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.ScreenDecorations;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarStateController.StateListener;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index e4a5caaf7d71..be4df458ecb9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -21,10 +21,9 @@ import android.view.MotionEvent;
import android.view.ViewConfiguration;
import com.android.systemui.Gefingerpoken;
+import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
/**
* A helper class to handle touches on the heads-up views.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 543949768f05..21c506b68319 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -54,6 +54,7 @@ import android.telecom.TelecomManager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.MathUtils;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
@@ -568,6 +569,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
mDarkAmount = darkAmount;
mIndicationController.setDarkAmount(darkAmount);
mLockIcon.setDarkAmount(darkAmount);
+ dozeTimeTick();
}
private static boolean isSuccessfulLaunch(int result) {
@@ -840,12 +842,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
public void dozeTimeTick() {
- if (mDarkAmount == 1) {
- // Move views every minute to avoid burn-in
- int burnInYOffset = getBurnInOffset(mBurnInYOffset * 2, false /* xAxis */)
- - mBurnInYOffset;
- mLockIcon.setTranslationY(burnInYOffset);
- }
+ // Move views every minute to avoid burn-in
+ int burnInYOffset = -getBurnInOffset(mBurnInYOffset, false /* xAxis */);
+ burnInYOffset = (int) MathUtils.lerp(0, burnInYOffset, mDarkAmount);
+ mLockIcon.setTranslationY(burnInYOffset);
}
public void setBurnInXOffset(int burnInXOffset) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 235629bbb509..c0d1818d8da9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -16,8 +16,8 @@
package com.android.systemui.statusbar.phone;
-import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import static com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import android.content.Context;
import android.content.res.ColorStateList;
@@ -268,6 +268,8 @@ public class KeyguardBouncer {
}
public void hide(boolean destroyView) {
+ // TODO(b/113914868): investigation log for disappearing home button
+ Log.i(TAG, "KeyguardBouncer.hide (b/113914868): destroyView=" + destroyView);
if (isShowing()) {
StatsLog.write(StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 8cace7206a1f..e0c5516417ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -16,7 +16,9 @@
package com.android.systemui.statusbar.phone;
-import android.app.WallpaperColors;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
+
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
@@ -32,9 +34,6 @@ import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
-
/**
* Controls how light status bar flag applies to the icons.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
index 27798203e4fe..7621887b4170 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
@@ -19,7 +19,6 @@ package com.android.systemui.statusbar.phone;
import android.metrics.LogMaker;
import android.util.ArrayMap;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index 673cdb7c78ac..d2023ec49ebc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -20,6 +20,7 @@ import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.IWallpaperManager;
import android.app.IWallpaperManagerCallback;
+import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.content.Context;
import android.content.res.Resources;
@@ -36,7 +37,6 @@ import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.app.WallpaperColors;
import android.util.Log;
import com.android.keyguard.KeyguardUpdateMonitor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 22b6ba6fbb25..7c31dae2a746 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -14,6 +14,8 @@
package com.android.systemui.statusbar.phone;
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
@@ -34,11 +36,11 @@ import android.widget.LinearLayout;
import android.widget.Space;
import com.android.systemui.Dependency;
-import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.R;
import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.phone.ReverseLinearLayout.ReverseRelativeLayout;
import com.android.systemui.statusbar.policy.KeyButtonView;
import com.android.systemui.tuner.TunerService;
@@ -48,8 +50,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-
public class NavigationBarInflaterView extends FrameLayout
implements Tunable, PluginListener<NavBarButtonProvider> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index d58b5543221e..12a0cc882a81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -26,7 +26,6 @@ import android.view.IWallpaperVisibilityListener;
import android.view.IWindowManager;
import android.view.MotionEvent;
import android.view.View;
-import android.view.View.OnLayoutChangeListener;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.Dependency;
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 b43bbdc2ca0d..2f58ca1c984b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -17,10 +17,15 @@
package com.android.systemui.statusbar.phone;
import static android.view.MotionEvent.ACTION_DOWN;
+
+import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
+import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_DEAD_ZONE;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW;
+import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ROTATION;
import android.animation.LayoutTransition;
import android.animation.LayoutTransition.TransitionListener;
@@ -60,15 +65,15 @@ import android.widget.FrameLayout;
import com.android.systemui.Dependency;
import com.android.systemui.DockedStackExistsListener;
import com.android.systemui.Interpolators;
-import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.plugins.statusbar.phone.NavGesture;
import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
+import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsOnboarding;
+import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.NavigationBarCompat;
import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -79,11 +84,6 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.function.Consumer;
-import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
-import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
-import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW;
-import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ROTATION;
-
public class NavigationBarView extends FrameLayout implements PluginListener<NavGesture> {
final static boolean DEBUG = false;
final static String TAG = "StatusBar/NavBarView";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java
index 593bfae2aa4c..83067f6cff87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationGestureAction.java
@@ -26,7 +26,6 @@ import android.content.Context;
import android.graphics.Canvas;
import android.view.MotionEvent;
-import android.view.WindowManagerPolicyConstants;
import com.android.systemui.recents.OverviewProxyService;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
index 1524f806f871..2a11c2676b0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NearestTouchFrame.java
@@ -16,17 +16,14 @@ package com.android.systemui.statusbar.phone;
import android.content.Context;
import android.content.res.Configuration;
-import android.graphics.Rect;
-import androidx.annotation.VisibleForTesting;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
-import com.android.systemui.R;
+import androidx.annotation.VisibleForTesting;
import java.util.ArrayList;
import java.util.Comparator;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
index e7ede6f626ba..ca762cdf07f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
@@ -20,7 +20,6 @@ import android.app.Fragment;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
-import androidx.annotation.DimenRes;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewStub;
@@ -28,6 +27,8 @@ import android.view.ViewStub.OnInflateListener;
import android.view.WindowInsets;
import android.widget.FrameLayout;
+import androidx.annotation.DimenRes;
+
import com.android.systemui.R;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index deac669e31d8..65b0ecc00953 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -22,7 +22,6 @@ import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
-import android.view.View;
import android.widget.FrameLayout;
public abstract class PanelBar extends FrameLayout {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 0e6efc8472b6..c84f3db8acb0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -66,6 +66,8 @@ import com.android.systemui.DockedStackExistsListener;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.UiOffloadThread;
+import com.android.systemui.privacy.PrivacyItem;
+import com.android.systemui.privacy.PrivacyItemController;
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -101,7 +103,8 @@ import java.util.Locale;
*/
public class PhoneStatusBarPolicy implements Callback, Callbacks,
RotationLockControllerCallback, Listener, LocationChangeCallback,
- ZenModeController.Callback, DeviceProvisionedListener, KeyguardMonitor.Callback {
+ ZenModeController.Callback, DeviceProvisionedListener, KeyguardMonitor.Callback,
+ PrivacyItemController.Callback {
private static final String TAG = "PhoneStatusBarPolicy";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -120,6 +123,8 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
private final String mSlotHeadset;
private final String mSlotDataSaver;
private final String mSlotLocation;
+ private final String mSlotMicrophone;
+ private final String mSlotCamera;
private final Context mContext;
private final Handler mHandler = new Handler();
@@ -136,6 +141,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
private final DeviceProvisionedController mProvisionedController;
private final KeyguardMonitor mKeyguardMonitor;
private final LocationController mLocationController;
+ private final PrivacyItemController mPrivacyItemController;
private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
@@ -169,6 +175,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
mProvisionedController = Dependency.get(DeviceProvisionedController.class);
mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
mLocationController = Dependency.get(LocationController.class);
+ mPrivacyItemController = new PrivacyItemController(mContext, this);
mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot);
@@ -183,6 +190,8 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset);
mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver);
mSlotLocation = context.getString(com.android.internal.R.string.status_bar_location);
+ mSlotMicrophone = context.getString(com.android.internal.R.string.status_bar_microphone);
+ mSlotCamera = context.getString(com.android.internal.R.string.status_bar_camera);
// listen for broadcasts
IntentFilter filter = new IntentFilter();
@@ -241,6 +250,12 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
context.getString(R.string.accessibility_data_saver_on));
mIconController.setIconVisibility(mSlotDataSaver, false);
+ // privacy items
+ mIconController.setIcon(mSlotMicrophone, R.drawable.stat_sys_mic_none, null);
+ mIconController.setIconVisibility(mSlotMicrophone, false);
+ mIconController.setIcon(mSlotCamera, R.drawable.stat_sys_camera, null);
+ mIconController.setIconVisibility(mSlotCamera, false);
+
mRotationLockController.addCallback(this);
mBluetooth.addCallback(this);
mProvisionedController.addCallback(this);
@@ -251,6 +266,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
mDataSaver.addCallback(this);
mKeyguardMonitor.addCallback(this);
mLocationController.addCallback(this);
+ mPrivacyItemController.setListening(true);
SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallbacks(this);
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskListener);
@@ -279,6 +295,7 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
mDataSaver.removeCallback(this);
mKeyguardMonitor.removeCallback(this);
mLocationController.removeCallback(this);
+ mPrivacyItemController.setListening(false);
SysUiServiceProvider.getComponent(mContext, CommandQueue.class).removeCallbacks(this);
mContext.unregisterReceiver(mIntentReceiver);
@@ -798,6 +815,34 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
mIconController.setIconVisibility(mSlotDataSaver, isDataSaving);
}
+ @Override // PrivacyItemController.Callback
+ public void privacyChanged(List<PrivacyItem> privacyItems) {
+ updatePrivacyItems(privacyItems);
+ }
+
+ private void updatePrivacyItems(List<PrivacyItem> items) {
+ boolean showCamera = false;
+ boolean showMicrophone = false;
+ boolean showLocation = false;
+ for (PrivacyItem item : items) {
+ switch (item.getPrivacyType()) {
+ case TYPE_CAMERA:
+ showCamera = true;
+ break;
+ case TYPE_LOCATION:
+ showLocation = true;
+ break;
+ case TYPE_MICROPHONE:
+ showMicrophone = true;
+ break;
+ }
+ }
+
+ mIconController.setIconVisibility(mSlotCamera, showCamera);
+ mIconController.setIconVisibility(mSlotMicrophone, showMicrophone);
+ mIconController.setIconVisibility(mSlotLocation, showLocation);
+ }
+
private final TaskStackChangeListener mTaskListener = new TaskStackChangeListener() {
@Override
public void onTaskStackChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java
index c64e12478098..74744f1408fb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubAction.java
@@ -34,7 +34,6 @@ import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.Shader;
import android.os.RemoteException;
-
import android.util.FloatProperty;
import android.util.Log;
import android.view.MotionEvent;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index 37c4c58a3bd9..0eff4d4adff5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -42,10 +42,10 @@ import android.view.ViewPropertyAnimator;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
-import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
import com.android.systemui.R;
-import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
+import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.shared.system.NavigationBarCompat;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
index c6e98e0cfeb3..a7b8eff959c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
@@ -39,10 +39,10 @@ import android.view.Surface;
import android.view.View;
import android.view.WindowManagerGlobal;
-import com.android.systemui.Dependency;
-import com.android.systemui.Interpolators;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
index 2a5028bbe181..f8731b4980d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenPinningNotify.java
@@ -19,7 +19,6 @@ package com.android.systemui.statusbar.phone;
import android.content.Context;
import android.os.SystemClock;
import android.util.Slog;
-import android.view.WindowManager;
import android.widget.Toast;
import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 1bed26dd3474..9f34cbb23131 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -23,7 +23,6 @@ import android.app.AlarmManager;
import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Color;
-import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Trace;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
index e546119968aa..f9262186968f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
@@ -15,6 +15,7 @@
package com.android.systemui.statusbar.phone;
import android.view.View;
+
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
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 12fbf2d979f4..a6a9d74a894c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -342,7 +342,8 @@ public class StatusBar extends SystemUI implements DemoMode,
private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
protected StatusBarWindowController mStatusBarWindowController;
protected UnlockMethodCache mUnlockMethodCache;
- private DozeServiceHost mDozeServiceHost = new DozeServiceHost();
+ @VisibleForTesting
+ DozeServiceHost mDozeServiceHost = new DozeServiceHost();
private boolean mWakeUpComingFromTouch;
private PointF mWakeUpTouchLocation;
@@ -479,7 +480,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private boolean mLaunchCameraOnScreenTurningOn;
private boolean mLaunchCameraOnFinishedGoingToSleep;
private int mLastCameraLaunchSource;
- private PowerManager.WakeLock mGestureWakeLock;
+ protected PowerManager.WakeLock mGestureWakeLock;
private Vibrator mVibrator;
private long[] mCameraLaunchGestureVibePattern;
@@ -3609,6 +3610,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
+ @VisibleForTesting
final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
@Override
public void onFinishedGoingToSleep() {
@@ -3650,6 +3652,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mNotificationPanel.setTouchAndAnimationDisabled(false);
updateVisibleToUser();
updateIsKeyguard();
+ mDozeServiceHost.stopDozing();
}
};
@@ -3856,7 +3859,8 @@ public class StatusBar extends SystemUI implements DemoMode,
return mStatusBarKeyguardViewManager.isShowing();
}
- private final class DozeServiceHost implements DozeHost {
+ @VisibleForTesting
+ final class DozeServiceHost implements DozeHost {
private final ArrayList<Callback> mCallbacks = new ArrayList<>();
private boolean mAnimateWakeup;
private boolean mAnimateScreenOff;
@@ -3944,7 +3948,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mDozingRequested = false;
DozeLog.traceDozing(mContext, mDozing);
updateDozing();
- mWakefulnessLifecycle.dispatchStartedWakingUp();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 0d6cb5c50077..26c9d288494d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -16,16 +16,15 @@ package com.android.systemui.statusbar.phone;
import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS;
import static android.app.StatusBarManager.DISABLE_NONE;
+
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_ICON;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE;
import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI;
import android.content.Context;
import android.os.Bundle;
-import androidx.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.util.ArraySet;
-import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
@@ -33,19 +32,22 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
+import androidx.annotation.VisibleForTesting;
+
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarMobileView;
import com.android.systemui.statusbar.StatusBarWifiView;
+import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.util.Utils.DisableStateTracker;
+
import java.util.List;
public interface StatusBarIconController {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index 24a589665600..7c17c018443e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -45,8 +45,6 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
-import static com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY;
-
/**
* Receives the callbacks from CommandQueue related to icons and tracks the state of
* all the icons. Dispatches this state to any IconManagers that are currently
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
index c4ff85fb7984..88d0035b333d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.java
@@ -20,6 +20,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.graphics.drawable.Icon;
import android.os.UserHandle;
+
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
index b7e1cfb0097b..2e4161787267 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
@@ -16,16 +16,17 @@
package com.android.systemui.statusbar.phone;
+import static com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
+
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.statusbar.StatusBarIcon;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
-import static com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY;
-
public class StatusBarIconList {
private ArrayList<Slot> mSlots = new ArrayList<>();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index f81ffe9ecb76..8286d26e9999 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -17,29 +17,20 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Rect;
import android.os.Handler;
-import android.os.Looper;
import android.telephony.SubscriptionInfo;
import android.util.ArraySet;
import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityEvent;
-import android.widget.ImageView;
-import com.android.settingslib.graph.SignalDrawable;
+
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
import com.android.systemui.statusbar.policy.SecurityController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index ad9b9b30fafc..978a72dcb4b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -33,7 +33,6 @@ import android.media.AudioManager;
import android.media.session.MediaSessionLegacyHelper;
import android.net.Uri;
import android.os.Bundle;
-import android.os.IBinder;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.ActionMode;
@@ -50,8 +49,6 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
-import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
import android.widget.FrameLayout;
import com.android.internal.annotations.VisibleForTesting;
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 56a177eb15fe..6495910359bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -16,9 +16,9 @@
package com.android.systemui.statusbar.phone;
-import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
import static com.android.systemui.statusbar.StatusBarIconView.STATE_DOT;
import static com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN;
+import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
import android.annotation.Nullable;
import android.content.Context;
@@ -28,14 +28,15 @@ import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.util.Log;
-
import android.view.View;
+
import com.android.keyguard.AlphaOptimizedLinearLayout;
import com.android.systemui.R;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.notification.stack.AnimationFilter;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ViewState;
+
import java.util.ArrayList;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index e5925f07017f..bdd76c8ea05a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -16,8 +16,8 @@
package com.android.systemui.statusbar.phone;
-import android.hardware.biometrics.BiometricSourceType;
import android.content.Context;
+import android.hardware.biometrics.BiometricSourceType;
import android.os.Trace;
import com.android.internal.widget.LockPatternUtils;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
index 2ed2edb969bd..ba55f2ddcf13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UserAvatarView.java
@@ -20,7 +20,6 @@ import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
-import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
index d85e18c17252..67da8a54b68a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
@@ -14,14 +14,11 @@
package com.android.systemui.statusbar.policy;
-import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
-import java.util.List;
-
/**
* For mocking because AccessibilityManager is final for some reason...
*/
@@ -62,8 +59,8 @@ public class AccessibilityManagerWrapper implements
mAccessibilityManager.sendAccessibilityEvent(event);
}
- public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(
- int feedbackTypeFlags) {
- return mAccessibilityManager.getEnabledAccessibilityServiceList(feedbackTypeFlags);
+ /** Returns a recommended ui timeout value in milliseconds. */
+ public int getRecommendedTimeoutMillis(int originalTimeout, int uiContentFlags) {
+ return mAccessibilityManager.getRecommendedTimeoutMillis(originalTimeout, uiContentFlags);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
index b76d536150eb..e1bb19a6f69f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
@@ -19,6 +19,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.telephony.SubscriptionInfo;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index 533bd86dbf5e..ccfe073d5cb8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.policy;
+import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
+
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -30,6 +32,8 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
+import androidx.annotation.VisibleForTesting;
+
import com.android.internal.annotations.GuardedBy;
import com.android.systemui.R;
@@ -40,10 +44,6 @@ import java.util.Objects;
import java.util.Set;
import java.util.UUID;
-import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
-
-import androidx.annotation.VisibleForTesting;
-
/** Platform implementation of the cast controller. **/
public class CastControllerImpl implements CastController {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
index 2ede327ab698..911715fdba63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
@@ -21,8 +21,6 @@ import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
-import com.android.systemui.statusbar.policy.DataSaverController.Listener;
-
import java.util.ArrayList;
public class DataSaverControllerImpl implements DataSaverController {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index dcce77c7c355..74a30fa8094f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -27,7 +27,6 @@ import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.TextView;
-import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
index cae76b492527..7b4c35a8d25a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
@@ -14,8 +14,6 @@
package com.android.systemui.statusbar.policy;
-import android.content.Context;
-
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
public interface DeviceProvisionedController extends CallbackController<DeviceProvisionedListener> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
index c7261899a786..0d6178b1176b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
@@ -23,13 +23,9 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.provider.Settings;
-import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.text.TextUtils;
import android.util.AttributeSet;
-import android.util.Log;
-import android.view.ViewGroup;
-import android.view.ViewParent;
import android.widget.TextView;
import com.android.internal.telephony.IccCardConstants;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
index 11fc40804f71..e23ce2d022b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
@@ -30,8 +30,6 @@ import android.provider.Settings.Secure;
import android.text.TextUtils;
import android.util.Log;
-import com.android.systemui.statusbar.policy.FlashlightController.FlashlightListener;
-
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
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 b4d24d16113e..6b83b70b0ca5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -16,22 +16,23 @@
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.NotificationInflater
+ .FLAG_CONTENT_VIEW_HEADS_UP;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
import android.database.ContentObserver;
-import android.util.ArrayMap;
import android.provider.Settings;
+import android.util.ArrayMap;
import android.util.Log;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.statusbar.AlertingNotificationManager;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java
index 5fd79a4bb342..aee021ce4688 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java
@@ -23,9 +23,10 @@ import android.content.Context;
import android.metrics.LogMaker;
import android.os.Handler;
import android.os.Looper;
-import androidx.annotation.VisibleForTesting;
import android.util.ArraySet;
+import androidx.annotation.VisibleForTesting;
+
import com.android.internal.logging.MetricsLogger;
import java.util.Arrays;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
index 2340786d81fb..03c89c60360f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
@@ -37,6 +37,7 @@ import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.util.FloatProperty;
import android.view.ContextThemeWrapper;
+
import com.android.settingslib.Utils;
import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
index 59bd85eaabd4..8b869969e215 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
@@ -25,9 +25,9 @@ import android.graphics.CanvasProperty;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
+import android.graphics.RecordingCanvas;
import android.graphics.drawable.Drawable;
import android.os.Handler;
-import android.graphics.RecordingCanvas;
import android.view.RenderNodeAnimator;
import android.view.View;
import android.view.ViewConfiguration;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 6fa73ef62447..2c756ceb1b48 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -45,12 +45,13 @@ import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ImageView;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
-import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
+import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.system.NavigationBarCompat;
public class KeyButtonView extends ImageView implements ButtonInterface {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index fcd7e0953825..840e77ea85a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -29,12 +29,14 @@ import android.location.LocationManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+
import androidx.annotation.VisibleForTesting;
+
import com.android.systemui.util.Utils;
+
import java.util.ArrayList;
import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 8ca14152f080..e943261bda7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -35,8 +35,8 @@ import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.cdma.EriInfo;
-import com.android.settingslib.graph.SignalDrawable;
import com.android.settingslib.Utils;
+import com.android.settingslib.graph.SignalDrawable;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
index dfdeae1fc497..dac878c69313 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
@@ -23,8 +23,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.UserHandle;
-import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
-
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java
index 5028fd1cec9e..d43476885979 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnHeadsUpChangedListener.java
@@ -16,8 +16,8 @@
package com.android.systemui.statusbar.policy;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
/**
* A listener to heads up changes
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 7dd0d0fbef47..a485fa89ebe8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -55,8 +55,8 @@ import com.android.internal.logging.nano.MetricsProto;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
index 91c208d571f5..9ec30d43ac75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
@@ -15,16 +15,17 @@
*/
package com.android.systemui.statusbar.policy;
+import static com.android.systemui.statusbar.policy.NetworkControllerImpl.TAG;
+
import android.content.Context;
import android.text.format.DateFormat;
import android.util.Log;
+
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import java.io.PrintWriter;
import java.util.BitSet;
-import static com.android.systemui.statusbar.policy.NetworkControllerImpl.TAG;
-
/**
* Common base class for handling signal for both wifi and mobile data.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
index 7b0b80049966..71d6e5421b75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.policy;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.database.ContentObserver;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index aa4782fd864a..42f1378a15dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -28,11 +28,11 @@ import android.widget.Button;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ContrastColorUtil;
-import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
index f5ae88b1788d..fed803217568 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
@@ -37,7 +37,6 @@ import android.util.Log;
import com.android.internal.util.UserIcons;
import com.android.settingslib.drawable.UserIconDrawable;
import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index b5d92a5840e0..cd379c5f551f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -25,7 +25,6 @@ import android.os.ServiceManager;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.SystemUI;
-import com.android.systemui.pip.tv.PipManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
index 499be42b0b8c..905b9a398b68 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
@@ -14,19 +14,21 @@
package com.android.systemui.tuner;
+import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
+
import android.content.Context;
import android.provider.Settings;
-import androidx.preference.DropDownPreference;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.AttributeSet;
+
+import androidx.preference.DropDownPreference;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.phone.StatusBarIconController;
-import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
-
public class BatteryPreference extends DropDownPreference implements TunerService.Tunable {
private static final String PERCENT = "percent";
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/BetterListPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/BetterListPreference.java
index 702abeabc136..265823ab0b21 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/BetterListPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/BetterListPreference.java
@@ -15,9 +15,10 @@
package com.android.systemui.tuner;
import android.content.Context;
-import androidx.preference.ListPreference;
import android.util.AttributeSet;
+import androidx.preference.ListPreference;
+
public class BetterListPreference extends ListPreference {
private CharSequence mSummary;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
index 16ab65c341ca..a526603372bd 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
@@ -14,11 +14,12 @@
package com.android.systemui.tuner;
import android.content.Context;
-import androidx.preference.DropDownPreference;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.AttributeSet;
+import androidx.preference.DropDownPreference;
+
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.Clock;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java
index 8da0043bf439..ade1f8258335 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/CustomListPreference.java
@@ -14,7 +14,6 @@
package com.android.systemui.tuner;
-import android.annotation.Nullable;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
@@ -22,12 +21,10 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
-import androidx.preference.ListPreferenceDialogFragment;
-import androidx.preference.ListPreference;
import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
+
+import androidx.preference.ListPreference;
+import androidx.preference.ListPreferenceDialogFragment;
public class CustomListPreference extends ListPreference {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
index a0f278bfbb8a..a60ca6201419 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
@@ -23,12 +23,13 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.SwitchPreference;
+import android.view.MenuItem;
+
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceChangeListener;
+import androidx.preference.PreferenceFragment;
import androidx.preference.PreferenceScreen;
-import android.view.MenuItem;
+import androidx.preference.SwitchPreference;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
index d63235ca8d26..4dbceac9b3a7 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
@@ -21,32 +21,25 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.LauncherActivityInfo;
-import android.content.pm.LauncherApps;
-import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ShortcutInfo;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.ScaleDrawable;
import android.os.Bundle;
import android.os.Handler;
-import android.os.Process;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.SwitchPreference;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceGroup;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import android.text.TextUtils;
-import android.util.Log;
import android.util.TypedValue;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragment;
+import androidx.preference.SwitchPreference;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
+
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.IntentButtonProvider.IntentButton;
@@ -57,7 +50,6 @@ import com.android.systemui.tuner.ShortcutParser.Shortcut;
import com.android.systemui.tuner.TunerService.Tunable;
import java.util.ArrayList;
-import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
index e3a452a0786a..fa531b5243b4 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/NavBarTuner.java
@@ -34,9 +34,6 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.Handler;
-import androidx.preference.ListPreference;
-import androidx.preference.Preference;
-import androidx.preference.Preference.OnPreferenceChangeListener;
import android.text.SpannableStringBuilder;
import android.text.style.ImageSpan;
import android.util.Log;
@@ -44,6 +41,10 @@ import android.util.TypedValue;
import android.view.KeyEvent;
import android.widget.EditText;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+import androidx.preference.Preference.OnPreferenceChangeListener;
+
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.tuner.TunerService.Tunable;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/OtherPrefs.java b/packages/SystemUI/src/com/android/systemui/tuner/OtherPrefs.java
index d766145f27db..7239c8a22a31 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/OtherPrefs.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/OtherPrefs.java
@@ -15,7 +15,9 @@
package com.android.systemui.tuner;
import android.os.Bundle;
+
import androidx.preference.PreferenceFragment;
+
import com.android.systemui.R;
public class OtherPrefs extends PreferenceFragment {
@@ -23,4 +25,4 @@ public class OtherPrefs extends PreferenceFragment {
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.other_settings);
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
index ecb830c48ccc..dae1472c42af 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
@@ -29,6 +29,11 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.view.View;
+import androidx.preference.PreferenceFragment;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.PreferenceViewHolder;
+import androidx.preference.SwitchPreference;
+
import com.android.internal.util.ArrayUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -41,11 +46,6 @@ import com.android.systemui.shared.plugins.PluginPrefs;
import java.util.List;
import java.util.Set;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.PreferenceViewHolder;
-import androidx.preference.SwitchPreference;
-
public class PluginFragment extends PreferenceFragment {
public static final String ACTION_PLUGIN_SETTINGS
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java
index 8740a3c2f45a..80f9de6b4ba5 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/PowerNotificationControlsFragment.java
@@ -15,10 +15,6 @@
*/
package com.android.systemui.tuner;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.R;
-
import android.annotation.Nullable;
import android.app.Fragment;
import android.os.Bundle;
@@ -29,6 +25,10 @@ import android.view.ViewGroup;
import android.widget.Switch;
import android.widget.TextView;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.R;
+
public class PowerNotificationControlsFragment extends Fragment {
private static final String KEY_SHOW_PNC = "show_importance_slider";
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java
index d80c649be1ba..79811c5de42d 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java
@@ -17,21 +17,19 @@ package com.android.systemui.tuner;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.DialogFragment;
-import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.View;
import android.widget.Toolbar;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
import com.android.settingslib.Utils;
-import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.R;
+import com.android.systemui.fragments.FragmentHostManager;
import java.util.Objects;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java b/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java
index dded464901ac..0be793eefa18 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/SelectablePreference.java
@@ -16,9 +16,10 @@ package com.android.systemui.tuner;
import android.content.Context;
import android.graphics.drawable.Drawable;
-import androidx.preference.CheckBoxPreference;
import android.util.TypedValue;
+import androidx.preference.CheckBoxPreference;
+
import com.android.systemui.statusbar.ScalingDrawableWrapper;
public class SelectablePreference extends CheckBoxPreference {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java b/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java
index 3c9d25d13350..11e1f278a271 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java
@@ -20,12 +20,12 @@ import android.content.Context;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.Process;
-import androidx.preference.PreferenceFragment;
+
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceFragment;
import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
index 670fcc2a4d15..6f23e207c048 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
@@ -19,10 +19,11 @@ import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
import android.provider.Settings;
-import androidx.preference.SwitchPreference;
import android.text.TextUtils;
import android.util.AttributeSet;
+import androidx.preference.SwitchPreference;
+
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 5aa303530ae5..ecf1784e66c4 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -22,12 +22,13 @@ import android.content.DialogInterface;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.Preference;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragment;
+
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java
index a22277eea05b..9cc8943aa6de 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerPreferenceFragment.java
@@ -15,9 +15,9 @@
package com.android.systemui.tuner;
import android.app.DialogFragment;
-import android.os.Bundle;
-import androidx.preference.PreferenceFragment;
+
import androidx.preference.Preference;
+import androidx.preference.PreferenceFragment;
public abstract class TunerPreferenceFragment extends PreferenceFragment {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index 3a9d1c7caeb8..3bccdab8c1ba 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -26,8 +26,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.os.UserHandle;
import android.provider.Settings;
-import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
-import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.SystemUIDialog;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
index f53d51690712..2df9000ed665 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java
@@ -3,9 +3,10 @@ package com.android.systemui.tuner;
import android.content.Context;
import android.content.res.TypedArray;
import android.provider.Settings;
-import androidx.preference.SwitchPreference;
import android.util.AttributeSet;
+import androidx.preference.SwitchPreference;
+
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Dependency;
import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 2f8dfdc2991a..329d02959435 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -19,7 +19,6 @@ package com.android.systemui.usb;
import android.annotation.NonNull;
import android.app.Notification;
import android.app.Notification.Action;
-import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
index ec5030b8b028..fa3ff64e5e18 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
@@ -16,6 +16,8 @@
package com.android.systemui.usb;
+import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
+
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.pm.ResolveInfo;
@@ -38,8 +40,6 @@ import com.android.systemui.R;
import java.util.ArrayList;
import java.util.Iterator;
-import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
-
/* Activity for choosing an application for a USB device or accessory */
public class UsbResolverActivity extends ResolverActivity {
public static final String TAG = "UsbResolverActivity";
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
index c468fef293de..f35af90edc3c 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -16,7 +16,6 @@ package com.android.systemui.util;
import android.app.NotificationChannel;
import android.app.NotificationManager;
-
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioAttributes;
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
index 9b15b00b9242..efd6e03b0d20 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
@@ -20,9 +20,10 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
-import androidx.core.content.FileProvider;
import android.util.Log;
+import androidx.core.content.FileProvider;
+
import com.android.systemui.Dependency;
import java.io.BufferedInputStream;
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
index 3c88d29f1711..b2cc2694916e 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
@@ -37,7 +37,6 @@ import android.os.Message;
import android.os.Process;
import android.os.SystemProperties;
import android.provider.Settings;
-import androidx.annotation.VisibleForTesting;
import android.service.quicksettings.Tile;
import android.text.format.DateUtils;
import android.util.Log;
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java b/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java
index 574fdb98caa7..c50e8f8a3596 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/LeakDetector.java
@@ -24,7 +24,6 @@ import com.android.systemui.Dumpable;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.io.Writer;
import java.util.Collection;
/**
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
index 8ea5fd4ee93c..a47e99d1e84d 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
@@ -27,9 +27,10 @@ import android.net.Uri;
import android.os.Debug;
import android.os.SystemProperties;
import android.os.UserHandle;
-import androidx.core.content.FileProvider;
import android.util.Log;
+import androidx.core.content.FileProvider;
+
import com.google.android.collect.Lists;
import java.io.File;
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
index f2ed55f3dd32..13729dfbccda 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/SettableWakeLock.java
@@ -16,9 +16,6 @@
package com.android.systemui.util.wakelock;
-import android.os.Handler;
-import android.os.PowerManager;
-
import com.android.internal.util.Preconditions;
public class SettableWakeLock {
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
index 16ce35c50ea2..b0f1b54b262e 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java
@@ -18,6 +18,7 @@ package com.android.systemui.util.wakelock;
import android.content.Context;
import android.os.PowerManager;
+
import androidx.annotation.VisibleForTesting;
/** WakeLock wrapper for testability */
@@ -71,4 +72,4 @@ public interface WakeLock {
}
};
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index 9077b6b10ac7..9b616e00a72f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -34,8 +34,8 @@ import android.content.ServiceConnection;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.PixelFormat;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.media.AudioAttributes;
import android.media.AudioManager;
@@ -65,17 +65,17 @@ import androidx.car.widget.ListItemProvider.ListProvider;
import androidx.car.widget.PagedListView;
import androidx.car.widget.SeekbarListItem;
-import java.util.Iterator;
+import com.android.systemui.R;
+import com.android.systemui.plugins.VolumeDialog;
+
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
-import com.android.systemui.R;
-import com.android.systemui.plugins.VolumeDialog;
-
/**
* Car version of the volume dialog.
*
diff --git a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
index c97095e1860b..361604c461b4 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java
@@ -27,7 +27,6 @@ import android.util.Log;
import android.view.KeyEvent;
import android.view.WindowManager;
-
import com.android.systemui.statusbar.phone.SystemUIDialog;
abstract public class SafetyWarningDialog extends SystemUIDialog
@@ -116,4 +115,4 @@ abstract public class SafetyWarningDialog extends SystemUIDialog
}
}
};
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
index 36c673c7106b..42393375b45e 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeComponent.java
@@ -19,7 +19,6 @@ package com.android.systemui.volume;
import android.content.res.Configuration;
import com.android.systemui.DemoMode;
-import com.android.systemui.statusbar.policy.ZenModeController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 798f8bcd7938..b5883052c9a2 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -16,8 +16,6 @@
package com.android.systemui.volume;
-import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK;
-import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_GENERIC;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.media.AudioManager.RINGER_MODE_NORMAL;
import static android.media.AudioManager.RINGER_MODE_SILENT;
@@ -32,7 +30,6 @@ import static android.view.View.VISIBLE;
import static com.android.systemui.volume.Events.DISMISS_REASON_SETTINGS_CLICKED;
-import android.accessibilityservice.AccessibilityServiceInfo;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
@@ -68,13 +65,12 @@ import android.view.ContextThemeWrapper;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.AccessibilityDelegate;
-import android.view.View.OnAttachStateChangeListener;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.view.Window;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
+import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
@@ -113,6 +109,10 @@ public class VolumeDialogImpl implements VolumeDialog {
private static final long USER_ATTEMPT_GRACE_PERIOD = 1000;
private static final int UPDATE_ANIMATION_DURATION = 80;
+ static final int DIALOG_TIMEOUT_MILLIS = 3000;
+ static final int DIALOG_SAFETYWARNING_TIMEOUT_MILLIS = 5000;
+ static final int DIALOG_HOVERING_TIMEOUT_MILLIS = 16000;
+
private final Context mContext;
private final H mHandler = new H();
private final VolumeDialogController mController;
@@ -170,7 +170,6 @@ public class VolumeDialogImpl implements VolumeDialog {
@Override
public void destroy() {
- mAccessibility.destroy();
mController.removeCallback(mControllerCallbackH);
mHandler.removeCallbacksAndMessages(null);
}
@@ -356,8 +355,6 @@ public class VolumeDialogImpl implements VolumeDialog {
writer.print(" mDynamic: "); writer.println(mDynamic);
writer.print(" mAutomute: "); writer.println(mAutomute);
writer.print(" mSilentMode: "); writer.println(mSilentMode);
- writer.print(" mAccessibility.mFeedbackEnabled: ");
- writer.println(mAccessibility.mFeedbackEnabled);
}
private static int getImpliedLevel(SeekBar seekBar, int progress) {
@@ -571,10 +568,18 @@ public class VolumeDialogImpl implements VolumeDialog {
}
private int computeTimeoutH() {
- if (mAccessibility.mFeedbackEnabled) return 20000;
- if (mHovering) return 16000;
- if (mSafetyWarning != null) return 5000;
- return 3000;
+ if (mHovering) {
+ return mAccessibilityMgr.getRecommendedTimeoutMillis(DIALOG_HOVERING_TIMEOUT_MILLIS,
+ AccessibilityManager.FLAG_CONTENT_CONTROLS);
+ }
+ if (mSafetyWarning != null) {
+ return mAccessibilityMgr.getRecommendedTimeoutMillis(
+ DIALOG_SAFETYWARNING_TIMEOUT_MILLIS,
+ AccessibilityManager.FLAG_CONTENT_TEXT
+ | AccessibilityManager.FLAG_CONTENT_CONTROLS);
+ }
+ return mAccessibilityMgr.getRecommendedTimeoutMillis(DIALOG_TIMEOUT_MILLIS,
+ AccessibilityManager.FLAG_CONTENT_CONTROLS);
}
protected void dismissH(int reason) {
@@ -1261,28 +1266,8 @@ public class VolumeDialogImpl implements VolumeDialog {
}
private final class Accessibility extends AccessibilityDelegate {
- private boolean mFeedbackEnabled;
-
public void init() {
- mDialogView.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
- @Override
- public void onViewDetachedFromWindow(View v) {
- if (D.BUG) Log.d(TAG, "onViewDetachedFromWindow");
- }
-
- @Override
- public void onViewAttachedToWindow(View v) {
- if (D.BUG) Log.d(TAG, "onViewAttachedToWindow");
- updateFeedbackEnabled();
- }
- });
mDialogView.setAccessibilityDelegate(this);
- mAccessibilityMgr.addCallback(mListener);
- updateFeedbackEnabled();
- }
-
- public void destroy() {
- mAccessibilityMgr.removeCallback(mListener);
}
@Override
@@ -1298,25 +1283,6 @@ public class VolumeDialogImpl implements VolumeDialog {
rescheduleTimeoutH();
return super.onRequestSendAccessibilityEvent(host, child, event);
}
-
- private void updateFeedbackEnabled() {
- mFeedbackEnabled = computeFeedbackEnabled();
- }
-
- private boolean computeFeedbackEnabled() {
- // are there any enabled non-generic a11y services?
- final List<AccessibilityServiceInfo> services =
- mAccessibilityMgr.getEnabledAccessibilityServiceList(FEEDBACK_ALL_MASK);
- for (AccessibilityServiceInfo asi : services) {
- if (asi.feedbackType != 0 && asi.feedbackType != FEEDBACK_GENERIC) {
- return true;
- }
- }
- return false;
- }
-
- private final AccessibilityServicesStateChangeListener mListener =
- enabled -> updateFeedbackEnabled();
}
private static class VolumeRow {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index 6f65b081afc4..e4f37decdf35 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -23,8 +23,6 @@ import android.util.Log;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.qs.tiles.DndTile;
-import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
import java.io.FileDescriptor;
import java.io.PrintWriter;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt
index 7204d310a76d..b23f667e4388 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt
@@ -27,55 +27,28 @@ import org.junit.runner.RunWith
@SmallTest
class PrivacyDialogBuilderTest : SysuiTestCase() {
- companion object {
- val MILLIS_IN_MINUTE: Long = 1000 * 60
- val NOW = 4 * MILLIS_IN_MINUTE
- }
-
@Test
- fun testGenerateText_multipleApps() {
+ fun testGenerateAppsList() {
val bar2 = PrivacyItem(Privacy.TYPE_CAMERA, PrivacyApplication(
- "Bar", context), 2 * MILLIS_IN_MINUTE)
+ "Bar", context))
val bar3 = PrivacyItem(Privacy.TYPE_LOCATION, PrivacyApplication(
- "Bar", context), 3 * MILLIS_IN_MINUTE)
+ "Bar", context))
val foo0 = PrivacyItem(Privacy.TYPE_CAMERA, PrivacyApplication(
- "Foo", context), 0)
+ "Foo", context))
val baz1 = PrivacyItem(Privacy.TYPE_CAMERA, PrivacyApplication(
- "Baz", context), 1 * MILLIS_IN_MINUTE)
+ "Baz", context))
val items = listOf(bar2, foo0, baz1, bar3)
val textBuilder = PrivacyDialogBuilder(context, items)
- val textList = textBuilder.generateText(NOW)
- assertEquals(2, textList.size)
- assertEquals("Bar, Foo, Baz are using your camera", textList[0])
- assertEquals("Bar is using your location for the last 1 min", textList[1])
- }
-
- @Test
- fun testGenerateText_singleApp() {
- val bar2 = PrivacyItem(Privacy.TYPE_CAMERA, PrivacyApplication(
- "Bar", context), 0)
- val bar1 = PrivacyItem(Privacy.TYPE_LOCATION, PrivacyApplication(
- "Bar", context), 0)
-
- val items = listOf(bar2, bar1)
-
- val textBuilder = PrivacyDialogBuilder(context, items)
- val textList = textBuilder.generateText(NOW)
- assertEquals(1, textList.size)
- assertEquals("Bar is using your camera, location", textList[0])
- }
-
- @Test
- fun testGenerateText_singleApp_singleType() {
- val bar2 = PrivacyItem(Privacy.TYPE_CAMERA, PrivacyApplication(
- "Bar", context), 2 * MILLIS_IN_MINUTE)
- val items = listOf(bar2)
- val textBuilder = PrivacyDialogBuilder(context, items)
- val textList = textBuilder.generateText(NOW)
- assertEquals(1, textList.size)
- assertEquals("Bar is using your camera for the last 2 min", textList[0])
+ val list = textBuilder.appsAndTypes
+ assertEquals(3, list.size)
+ val appsList = list.map { it.first }
+ val typesList = list.map { it.second }
+ assertEquals(listOf("Bar", "Baz", "Foo"), appsList.map { it.packageName })
+ assertEquals(listOf(Privacy.TYPE_CAMERA, Privacy.TYPE_LOCATION), typesList[0])
+ assertEquals(listOf(Privacy.TYPE_CAMERA), typesList[1])
+ assertEquals(listOf(Privacy.TYPE_CAMERA), typesList[2])
}
} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
index 8e6bfe3a5f91..f59bfaebb31d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
@@ -72,6 +72,8 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -390,10 +392,16 @@ public class NotificationDataTest extends SysuiTestCase {
@Test
public void testCreateNotificationDataEntry_RankingUpdate() {
Ranking ranking = mock(Ranking.class);
+ initStatusBarNotification(false);
+
+ List<Notification.Action> appGeneratedSmartActions =
+ Collections.singletonList(createContextualAction("appGeneratedAction"));
+ mMockStatusBarNotification.getNotification().actions =
+ appGeneratedSmartActions.toArray(new Notification.Action[0]);
- ArrayList<Notification.Action> smartActions = new ArrayList<>();
- smartActions.add(createAction());
- when(ranking.getSmartActions()).thenReturn(smartActions);
+ List<Notification.Action> systemGeneratedSmartActions =
+ Collections.singletonList(createAction("systemGeneratedAction"));
+ when(ranking.getSmartActions()).thenReturn(systemGeneratedSmartActions);
when(ranking.getChannel()).thenReturn(NOTIFICATION_CHANNEL);
@@ -407,7 +415,7 @@ public class NotificationDataTest extends SysuiTestCase {
NotificationData.Entry entry =
new NotificationData.Entry(mMockStatusBarNotification, ranking);
- assertEquals(smartActions, entry.smartActions);
+ assertEquals(systemGeneratedSmartActions, entry.systemGeneratedSmartActions);
assertEquals(NOTIFICATION_CHANNEL, entry.channel);
assertEquals(Ranking.USER_SENTIMENT_NEGATIVE, entry.userSentiment);
assertEquals(snoozeCriterions, entry.snoozeCriteria);
@@ -459,10 +467,20 @@ public class NotificationDataTest extends SysuiTestCase {
}
}
- private Notification.Action createAction() {
+ private Notification.Action createContextualAction(String title) {
+ return new Notification.Action.Builder(
+ Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
+ title,
+ PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0))
+ .setSemanticAction(
+ Notification.Action.SEMANTIC_ACTION_CONTEXTUAL_SUGGESTION)
+ .build();
+ }
+
+ private Notification.Action createAction(String title) {
return new Notification.Action.Builder(
Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon),
- "action",
+ title,
PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), 0)).build();
}
}
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 9f8a5cc0afdf..d1fe5af406d3 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
@@ -438,8 +438,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
mEntryManager.updateNotificationRanking(mRankingMap);
verify(mRow).setEntry(eq(mEntry));
- assertEquals(1, mEntry.smartActions.size());
- assertEquals("action", mEntry.smartActions.get(0).title);
+ assertEquals(1, mEntry.systemGeneratedSmartActions.size());
+ assertEquals("action", mEntry.systemGeneratedSmartActions.get(0).title);
}
@Test
@@ -453,7 +453,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
mEntryManager.updateNotificationRanking(mRankingMap);
verify(mRow, never()).setEntry(eq(mEntry));
- assertEquals(0, mEntry.smartActions.size());
+ assertEquals(0, mEntry.systemGeneratedSmartActions.size());
}
@Test
@@ -467,8 +467,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
mEntryManager.updateNotificationRanking(mRankingMap);
verify(mRow, never()).setEntry(eq(mEntry));
- assertEquals(1, mEntry.smartActions.size());
- assertEquals("action", mEntry.smartActions.get(0).title);
+ assertEquals(1, mEntry.systemGeneratedSmartActions.size());
+ assertEquals("action", mEntry.systemGeneratedSmartActions.get(0).title);
}
@Test
@@ -482,8 +482,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
mEntryManager.updateNotificationRanking(mRankingMap);
verify(mRow, never()).setEntry(eq(mEntry));
- assertEquals(1, mEntry.smartActions.size());
- assertEquals("action", mEntry.smartActions.get(0).title);
+ assertEquals(1, mEntry.systemGeneratedSmartActions.size());
+ assertEquals("action", mEntry.systemGeneratedSmartActions.get(0).title);
}
private Notification.Action createAction() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 626726d4aa4f..3d2ea708e90e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -284,7 +284,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
when(row.getIsNonblockable()).thenReturn(false);
StatusBarNotification statusBarNotification = row.getStatusBarNotification();
- mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView,
+ NotificationInfo.ACTION_NONE);
verify(notificationInfoView).bindNotification(
any(PackageManager.class),
@@ -301,7 +302,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
eq(true) /* isForBlockingHelper */,
eq(true) /* isUserSentimentNegative */,
eq(false) /*isNoisy */,
- eq(0));
+ eq(0),
+ eq(NotificationInfo.ACTION_NONE));
}
@Test
@@ -313,7 +315,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
when(row.getIsNonblockable()).thenReturn(false);
StatusBarNotification statusBarNotification = row.getStatusBarNotification();
- mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView,
+ NotificationInfo.ACTION_NONE);
verify(notificationInfoView).bindNotification(
any(PackageManager.class),
@@ -330,7 +333,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
eq(false) /* isForBlockingHelper */,
eq(true) /* isUserSentimentNegative */,
eq(false) /*isNoisy */,
- eq(0));
+ eq(0),
+ eq(NotificationInfo.ACTION_NONE));
}
@Test
@@ -343,7 +347,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
when(row.getIsNonblockable()).thenReturn(false);
StatusBarNotification statusBarNotification = row.getStatusBarNotification();
- mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView,
+ NotificationInfo.ACTION_NONE);
verify(notificationInfoView).bindNotification(
any(PackageManager.class),
@@ -360,7 +365,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
eq(true) /* isForBlockingHelper */,
eq(true) /* isUserSentimentNegative */,
eq(true) /*isNoisy */,
- eq(0));
+ eq(0),
+ eq(NotificationInfo.ACTION_NONE));
}
@Test
@@ -373,7 +379,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
when(row.getIsNonblockable()).thenReturn(false);
StatusBarNotification statusBarNotification = row.getStatusBarNotification();
- mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView,
+ NotificationInfo.ACTION_NONE);
verify(notificationInfoView).bindNotification(
any(PackageManager.class),
@@ -390,7 +397,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
eq(true) /* isForBlockingHelper */,
eq(true) /* isUserSentimentNegative */,
eq(false) /*isNoisy */,
- eq(IMPORTANCE_DEFAULT));
+ eq(IMPORTANCE_DEFAULT),
+ eq(NotificationInfo.ACTION_NONE));
}
@Test
@@ -403,7 +411,8 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
StatusBarNotification statusBarNotification = row.getStatusBarNotification();
when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
- mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView,
+ NotificationInfo.ACTION_NONE);
verify(notificationInfoView).bindNotification(
any(PackageManager.class),
@@ -420,7 +429,39 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
eq(false) /* isForBlockingHelper */,
eq(true) /* isUserSentimentNegative */,
eq(false) /*isNoisy */,
- eq(0));
+ eq(0),
+ eq(NotificationInfo.ACTION_NONE));
+ }
+
+ @Test
+ public void testInitializeNotificationInfoView_withInitialAction() throws Exception {
+ NotificationInfo notificationInfoView = mock(NotificationInfo.class);
+ ExpandableNotificationRow row = spy(mHelper.createRow());
+ row.setBlockingHelperShowing(true);
+ row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+ when(row.getIsNonblockable()).thenReturn(false);
+ StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+
+ mGutsManager.initializeNotificationInfo(row, notificationInfoView,
+ NotificationInfo.ACTION_BLOCK);
+
+ verify(notificationInfoView).bindNotification(
+ any(PackageManager.class),
+ any(INotificationManager.class),
+ eq(statusBarNotification.getPackageName()),
+ any(NotificationChannel.class),
+ anyInt(),
+ eq(statusBarNotification),
+ any(NotificationInfo.CheckSaveListener.class),
+ any(NotificationInfo.OnSettingsClickListener.class),
+ any(NotificationInfo.OnAppSettingsClickListener.class),
+ eq(false),
+ eq(false),
+ eq(true) /* isForBlockingHelper */,
+ eq(true) /* isUserSentimentNegative */,
+ eq(false) /*isNoisy */,
+ eq(0),
+ eq(NotificationInfo.ACTION_BLOCK));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index 37441963e32d..1cc1c637983b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -187,7 +187,7 @@ public class NotificationInfoTest extends SysuiTestCase {
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView textView = mNotificationInfo.findViewById(R.id.pkgname);
assertTrue(textView.getText().toString().contains("App Name"));
assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
@@ -200,7 +200,7 @@ public class NotificationInfoTest extends SysuiTestCase {
.thenReturn(iconDrawable);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final ImageView iconView = mNotificationInfo.findViewById(R.id.pkgicon);
assertEquals(iconDrawable, iconView.getDrawable());
}
@@ -209,7 +209,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(GONE, groupNameView.getVisibility());
final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
@@ -226,7 +226,7 @@ public class NotificationInfoTest extends SysuiTestCase {
.thenReturn(notificationChannelGroup);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(View.VISIBLE, groupNameView.getVisibility());
assertEquals("Test Group Name", groupNameView.getText());
@@ -238,7 +238,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_SetsTextChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(TEST_CHANNEL_NAME, textView.getText());
}
@@ -247,7 +247,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_DefaultChannelDoesNotUseChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
- false, false, IMPORTANCE_DEFAULT);
+ false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(GONE, textView.getVisibility());
}
@@ -260,7 +260,7 @@ public class NotificationInfoTest extends SysuiTestCase {
eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(10);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
- false, false, IMPORTANCE_DEFAULT);
+ false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(VISIBLE, textView.getVisibility());
}
@@ -269,7 +269,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_UnblockablePackageUsesChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(VISIBLE, textView.getVisibility());
}
@@ -278,7 +278,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_BlockButton() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final View block = mNotificationInfo.findViewById(R.id.block);
final View toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
final View minimize = mNotificationInfo.findViewById(R.id.minimize);
@@ -292,7 +292,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT);
+ true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
assertEquals(VISIBLE, toggleSilent.getVisibility());
assertEquals(
@@ -304,7 +304,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_LOW);
+ true, IMPORTANCE_LOW, NotificationInfo.ACTION_NONE);
final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
assertEquals(VISIBLE, toggleSilent.getVisibility());
assertEquals(
@@ -316,7 +316,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT);
+ true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
assertEquals(VISIBLE, toggleSilent.getVisibility());
assertEquals(
@@ -329,7 +329,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_LOW);
+ true, IMPORTANCE_LOW, NotificationInfo.ACTION_NONE);
final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
assertEquals(VISIBLE, toggleSilent.getVisibility());
assertEquals(
@@ -341,7 +341,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final View block = mNotificationInfo.findViewById(R.id.block);
final View minimize = mNotificationInfo.findViewById(R.id.minimize);
assertEquals(GONE, block.getVisibility());
@@ -356,7 +356,7 @@ public class NotificationInfoTest extends SysuiTestCase {
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mNotificationChannel, c);
latch.countDown();
- }, null, true, false, false, IMPORTANCE_DEFAULT);
+ }, null, true, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
settingsButton.performClick();
@@ -368,7 +368,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
}
@@ -380,7 +380,7 @@ public class NotificationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mNotificationChannel, c);
- }, null, false, false, false, IMPORTANCE_DEFAULT);
+ }, null, false, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
}
@@ -389,11 +389,11 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_SettingsButtonReappearsAfterSecondBind() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
(View v, NotificationChannel c, int appUid) -> {
- }, null, true, false, false, IMPORTANCE_DEFAULT);
+ }, null, true, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertEquals(View.VISIBLE, settingsButton.getVisibility());
}
@@ -402,7 +402,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testLogBlockingHelperCounter_doesntLogForNormalGutsView() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
verify(mMetricsLogger, times(0)).count(anyString(), anyInt());
}
@@ -411,7 +411,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testLogBlockingHelperCounter_logsForBlockingHelper() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, true,
- true, true, false, IMPORTANCE_DEFAULT);
+ true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
verify(mMetricsLogger, times(1)).count(anyString(), anyInt());
}
@@ -424,7 +424,7 @@ public class NotificationInfoTest extends SysuiTestCase {
(View v, NotificationChannel c, int appUid) -> {
assertEquals(null, c);
latch.countDown();
- }, null, true, true, false, IMPORTANCE_DEFAULT);
+ }, null, true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.info).performClick();
// Verify that listener was triggered.
@@ -437,7 +437,7 @@ public class NotificationInfoTest extends SysuiTestCase {
throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
- null, true, true, false, IMPORTANCE_DEFAULT);
+ null, true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView channelNameView =
mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(GONE, channelNameView.getVisibility());
@@ -448,7 +448,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testStopInvisibleIfBundleFromDifferentChannels() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
- null, true, true, false, IMPORTANCE_DEFAULT);
+ null, true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView blockView = mNotificationInfo.findViewById(R.id.block);
assertEquals(GONE, blockView.getVisibility());
}
@@ -457,7 +457,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testbindNotification_BlockingHelper() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, false,
- true, true, false, IMPORTANCE_DEFAULT);
+ true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
assertEquals(View.VISIBLE, view.getVisibility());
assertEquals(mContext.getString(R.string.inline_blocking_helper), view.getText());
@@ -467,7 +467,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testbindNotification_UnblockableTextVisibleWhenAppUnblockable() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
assertEquals(View.VISIBLE, view.getVisibility());
assertEquals(mContext.getString(R.string.notification_unblockable_desc),
@@ -478,7 +478,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mTestableLooper.processAllMessages();
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), any());
@@ -489,7 +489,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -503,7 +503,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.minimize).performClick();
mTestableLooper.processAllMessages();
@@ -517,7 +517,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT);
+ true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
mTestableLooper.processAllMessages();
@@ -531,7 +531,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT);
+ true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
mTestableLooper.processAllMessages();
@@ -545,7 +545,7 @@ public class NotificationInfoTest extends SysuiTestCase {
int originalImportance = mNotificationChannel.getImportance();
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.handleCloseControls(true, false);
mTestableLooper.processAllMessages();
@@ -560,7 +560,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.handleCloseControls(true, false);
@@ -578,7 +578,8 @@ public class NotificationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
- true, false /* isNonblockable */, false, /* isNoisy */IMPORTANCE_DEFAULT);
+ true, false /* isNonblockable */, false /* isNoisy */, IMPORTANCE_DEFAULT,
+ NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -598,8 +599,9 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
- null /* onSettingsClick */, null /* onAppSettingsClick */ ,
- true, false /* isNonblockable */, false, /* isNoisy */IMPORTANCE_DEFAULT);
+ null /* onSettingsClick */, null /* onAppSettingsClick */,
+ true, false /* isNonblockable */, false /* isNoisy */, IMPORTANCE_DEFAULT,
+ NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -620,7 +622,8 @@ public class NotificationInfoTest extends SysuiTestCase {
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */, false, /* isNoisy */IMPORTANCE_DEFAULT);
+ true /* isUserSentimentNegative */, false /* isNoisy */, IMPORTANCE_DEFAULT,
+ NotificationInfo.ACTION_NONE);
NotificationGuts guts = spy(new NotificationGuts(mContext, null));
when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
@@ -648,7 +651,8 @@ public class NotificationInfoTest extends SysuiTestCase {
10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */ , true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */, false, /* isNoisy */IMPORTANCE_DEFAULT);
+ true /* isUserSentimentNegative */, false /* isNoisy */, IMPORTANCE_DEFAULT,
+ NotificationInfo.ACTION_NONE);
NotificationGuts guts = spy(new NotificationGuts(mContext, null));
when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
@@ -676,8 +680,8 @@ public class NotificationInfoTest extends SysuiTestCase {
10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true, true /* isUserSentimentNegative */, false, /* isNoisy */
- IMPORTANCE_DEFAULT);
+ true, true /* isUserSentimentNegative */, false /* isNoisy */,
+ IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
@@ -696,7 +700,8 @@ public class NotificationInfoTest extends SysuiTestCase {
null /* onSettingsClick */, null /* onAppSettingsClick */,
true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */, false, /* isNoisy */IMPORTANCE_DEFAULT);
+ true /* isUserSentimentNegative */, false /* isNoisy */, IMPORTANCE_DEFAULT,
+ NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -719,7 +724,7 @@ public class NotificationInfoTest extends SysuiTestCase {
true /* isForBlockingHelper */,
true,
false /* isUserSentimentNegative */,
- false, /* isNoisy */IMPORTANCE_DEFAULT);
+ false /* isNoisy */, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
NotificationGuts guts = mock(NotificationGuts.class);
doCallRealMethod().when(guts).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
mNotificationInfo.setGutsParent(guts);
@@ -734,7 +739,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -748,7 +753,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -781,7 +786,7 @@ public class NotificationInfoTest extends SysuiTestCase {
false /* isNonblockable */,
true /* isForBlockingHelper */,
true /* isUserSentimentNegative */,
- false, /* isNoisy */IMPORTANCE_DEFAULT);
+ false/* isNoisy */, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -803,7 +808,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -818,7 +823,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -839,7 +844,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.handleCloseControls(true, false);
@@ -857,7 +862,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -879,7 +884,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -901,7 +906,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT);
+ true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
waitForUndoButton();
@@ -922,7 +927,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
waitForUndoButton();
@@ -944,7 +949,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT);
+ true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
waitForUndoButton();
@@ -966,7 +971,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_LOW);
+ false, IMPORTANCE_LOW, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
waitForUndoButton();
@@ -987,7 +992,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -1003,7 +1008,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -1020,7 +1025,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
(Runnable saveImportance, StatusBarNotification sbn) -> {
- }, null, null, true, true, false, IMPORTANCE_DEFAULT);
+ }, null, null, true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -1038,7 +1043,8 @@ public class NotificationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
(Runnable saveImportance, StatusBarNotification sbn) -> {
saveImportance.run();
- }, null, null, true, false, false, IMPORTANCE_DEFAULT);
+ }, null, null, true, false, false, IMPORTANCE_DEFAULT,
+ NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -1074,7 +1080,7 @@ public class NotificationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null,
(View v, Intent intent) -> {
latch.countDown();
- }, true, false, false, IMPORTANCE_DEFAULT);
+ }, true, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(View.VISIBLE, settingsLink.getVisibility());
settingsLink.performClick();
@@ -1102,7 +1108,7 @@ public class NotificationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
(View v, Intent intent) -> {
latch.countDown();
- }, true, false, false, IMPORTANCE_DEFAULT);
+ }, true, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(View.VISIBLE, settingsLink.getVisibility());
settingsLink.performClick();
@@ -1121,7 +1127,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
- null, true, false, false, IMPORTANCE_DEFAULT);
+ null, true, false, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(GONE, settingsLink.getVisibility());
}
@@ -1142,7 +1148,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(GONE, settingsLink.getVisibility());
}
@@ -1165,7 +1171,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, false, true,
- true, true, false, IMPORTANCE_DEFAULT);
+ true, true, false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
assertEquals(GONE, settingsLink.getVisibility());
}
@@ -1182,7 +1188,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -1195,7 +1201,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -1208,7 +1214,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- true, IMPORTANCE_DEFAULT);
+ true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
waitForUndoButton();
@@ -1222,7 +1228,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- true, IMPORTANCE_DEFAULT);
+ true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
waitForUndoButton();
@@ -1236,7 +1242,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -1248,7 +1254,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_NONE);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -1256,4 +1262,60 @@ public class NotificationInfoTest extends SysuiTestCase {
waitForStopButton();
assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
}
+
+ @Test
+ public void testBindNotificationWithInitialBlockAction() throws Exception {
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ false, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_BLOCK);
+ waitForUndoButton();
+ mNotificationInfo.handleCloseControls(true, false);
+
+ mTestableLooper.processAllMessages();
+ ArgumentCaptor<NotificationChannel> updated =
+ ArgumentCaptor.forClass(NotificationChannel.class);
+ verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), updated.capture());
+ assertTrue((updated.getValue().getUserLockedFields()
+ & USER_LOCKED_IMPORTANCE) != 0);
+ assertEquals(IMPORTANCE_NONE, updated.getValue().getImportance());
+ }
+
+ @Test
+ public void testBindNotificationWithInitialSilenceAction() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_DEFAULT, NotificationInfo.ACTION_TOGGLE_SILENT);
+ waitForUndoButton();
+ mNotificationInfo.handleCloseControls(true, false);
+
+ mTestableLooper.processAllMessages();
+ ArgumentCaptor<NotificationChannel> updated =
+ ArgumentCaptor.forClass(NotificationChannel.class);
+ verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), updated.capture());
+ assertTrue((updated.getValue().getUserLockedFields()
+ & USER_LOCKED_IMPORTANCE) != 0);
+ assertEquals(IMPORTANCE_LOW, updated.getValue().getImportance());
+ }
+
+ @Test
+ public void testBindNotificationWithInitialUnSilenceAction() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true, IMPORTANCE_LOW, NotificationInfo.ACTION_TOGGLE_SILENT);
+ waitForUndoButton();
+ mNotificationInfo.handleCloseControls(true, false);
+
+ mTestableLooper.processAllMessages();
+ ArgumentCaptor<NotificationChannel> updated =
+ ArgumentCaptor.forClass(NotificationChannel.class);
+ verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+ anyString(), eq(TEST_UID), updated.capture());
+ assertTrue((updated.getValue().getUserLockedFields()
+ & USER_LOCKED_IMPORTANCE) != 0);
+ assertEquals(IMPORTANCE_HIGH, updated.getValue().getImportance());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index 23365a419d31..1481aef6c2f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -19,22 +19,22 @@ package com.android.systemui.statusbar.phone;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import android.hardware.display.ColorDisplayManager;
import android.os.Handler;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
+
import com.android.internal.app.ColorDisplayController;
-import com.android.systemui.Dependency;
-import com.android.systemui.Prefs;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.qs.AutoAddTracker;
import com.android.systemui.qs.QSTileHost;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@@ -56,7 +56,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
@Test
public void nightTileAdded_whenActivated() {
- if (!ColorDisplayController.isAvailable(mContext)) {
+ if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) {
return;
}
mAutoTileManager.mColorDisplayCallback.onActivated(true);
@@ -65,7 +65,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
@Test
public void nightTileNotAdded_whenDeactivated() {
- if (!ColorDisplayController.isAvailable(mContext)) {
+ if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) {
return;
}
mAutoTileManager.mColorDisplayCallback.onActivated(false);
@@ -74,7 +74,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
@Test
public void nightTileAdded_whenNightModeTwilight() {
- if (!ColorDisplayController.isAvailable(mContext)) {
+ if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) {
return;
}
mAutoTileManager.mColorDisplayCallback.onAutoModeChanged(
@@ -84,7 +84,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
@Test
public void nightTileAdded_whenNightModeCustom() {
- if (!ColorDisplayController.isAvailable(mContext)) {
+ if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) {
return;
}
mAutoTileManager.mColorDisplayCallback.onAutoModeChanged(
@@ -94,7 +94,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
@Test
public void nightTileNotAdded_whenNightModeDisabled() {
- if (!ColorDisplayController.isAvailable(mContext)) {
+ if (!ColorDisplayManager.isNightDisplayAvailable(mContext)) {
return;
}
mAutoTileManager.mColorDisplayCallback.onAutoModeChanged(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 882f2615f443..d442de20db1e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -593,6 +593,30 @@ public class StatusBarTest extends SysuiTestCase {
verify(mStatusBarStateController).setState(eq(StatusBarState.FULLSCREEN_USER_SWITCHER));
}
+ @Test
+ public void testStartStopDozing() {
+ mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
+ when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true);
+
+ mStatusBar.mDozeServiceHost.startDozing();
+ verify(mStatusBarStateController).setIsDozing(eq(true));
+
+ mStatusBar.mDozeServiceHost.stopDozing();
+ verify(mStatusBarStateController).setIsDozing(eq(false));
+ }
+
+ @Test
+ public void testOnStartedWakingUp_isNotDozing() {
+ mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
+ when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true);
+
+ mStatusBar.mDozeServiceHost.startDozing();
+ verify(mStatusBarStateController).setIsDozing(eq(true));
+
+ mStatusBar.mWakefulnessObserver.onStartedWakingUp();
+ verify(mStatusBarStateController).setIsDozing(eq(false));
+ }
+
static class TestableStatusBar extends StatusBar {
public TestableStatusBar(StatusBarKeyguardViewManager man,
UnlockMethodCache unlock, KeyguardIndicationController key,
@@ -642,6 +666,7 @@ public class StatusBarTest extends SysuiTestCase {
mLockscreenUserManager = notificationLockscreenUserManager;
mCommandQueue = commandQueue;
mPresenter = notificationPresenter;
+ mGestureWakeLock = mock(PowerManager.WakeLock.class);
}
private WakefulnessLifecycle createAwakeWakefulnessLifecycle() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
index c536dca68def..5f02fad06b50 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -27,18 +27,23 @@ import static com.android.systemui.volume.VolumeDialogControllerImpl.STREAMS;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.KeyguardManager;
import android.media.AudioManager;
+import android.os.SystemClock;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.text.TextUtils;
+import android.view.InputDevice;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
import android.widget.ImageView;
import com.android.systemui.R;
@@ -48,10 +53,11 @@ import com.android.systemui.plugins.VolumeDialogController.State;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.function.Predicate;
@@ -59,7 +65,6 @@ import java.util.function.Predicate;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
-@Ignore
public class VolumeDialogImplTest extends SysuiTestCase {
VolumeDialogImpl mDialog;
@@ -113,6 +118,45 @@ public class VolumeDialogImplTest extends SysuiTestCase {
+ " failed test", condition.test(view));
}
}
+
+ @Test
+ public void testComputeTimeout() {
+ Mockito.reset(mAccessibilityMgr);
+ mDialog.rescheduleTimeoutH();
+ verify(mAccessibilityMgr).getRecommendedTimeoutMillis(
+ VolumeDialogImpl.DIALOG_TIMEOUT_MILLIS,
+ AccessibilityManager.FLAG_CONTENT_CONTROLS);
+ }
+
+ @Test
+ public void testComputeTimeout_withHovering() {
+ Mockito.reset(mAccessibilityMgr);
+ View dialog = mDialog.getDialogView();
+ long uptimeMillis = SystemClock.uptimeMillis();
+ MotionEvent event = MotionEvent.obtain(uptimeMillis, uptimeMillis,
+ MotionEvent.ACTION_HOVER_ENTER, 0, 0, 0);
+ event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+ dialog.dispatchGenericMotionEvent(event);
+ event.recycle();
+ verify(mAccessibilityMgr).getRecommendedTimeoutMillis(
+ VolumeDialogImpl.DIALOG_HOVERING_TIMEOUT_MILLIS,
+ AccessibilityManager.FLAG_CONTENT_CONTROLS);
+ }
+
+ @Test
+ public void testComputeTimeout_withSafetyWarningOn() {
+ Mockito.reset(mAccessibilityMgr);
+ ArgumentCaptor<VolumeDialogController.Callbacks> controllerCallbackCapture =
+ ArgumentCaptor.forClass(VolumeDialogController.Callbacks.class);
+ verify(mController).addCallback(controllerCallbackCapture.capture(), any());
+ VolumeDialogController.Callbacks callbacks = controllerCallbackCapture.getValue();
+ callbacks.onShowSafetyWarning(AudioManager.FLAG_SHOW_UI);
+ verify(mAccessibilityMgr).getRecommendedTimeoutMillis(
+ VolumeDialogImpl.DIALOG_SAFETYWARNING_TIMEOUT_MILLIS,
+ AccessibilityManager.FLAG_CONTENT_TEXT
+ | AccessibilityManager.FLAG_CONTENT_CONTROLS);
+ }
+
/*
@Test
public void testContentDescriptions() {
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 8ae587296d45..3e07d12b9a99 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -844,6 +844,8 @@ message MetricsEvent {
// PACKAGE: App that posted the notification
// DETAIL: Notification is expanded by user.
// PACKAGE: App that posted the notification
+ // COLLAPSE: Notification is collapsed by user.
+ // PACKAGE: App that posted the notification
// DISMISS: Notification is dismissed.
// PACKAGE: App that posted the notification
// SUBTYPE: Dismiss reason from NotificationManagerService.java
@@ -6596,6 +6598,12 @@ message MetricsEvent {
// OS: Q
NOTIFICATION_ZEN_MODE_OVERRIDING_APP = 1589;
+ // ACTION: User sent a direct reply
+ // PACKAGE: App that posted the notification
+ // CATEGORY: NOTIFICATION
+ // OS: Q
+ NOTIFICATION_DIRECT_REPLY_ACTION = 1590;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 033e99605d3f..11963d2a2c89 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -1674,4 +1674,20 @@ message WifiLinkLayerUsageStats {
// Total time the wifi radio is scanning in ms over the logging duration.
optional int64 radio_scan_time_ms = 5;
+
+ // Total time the wifi radio spent doing nan scans in ms over the logging duration.
+ optional int64 radio_nan_scan_time_ms = 6;
+
+ // Total time the wifi radio spent doing background scans in ms over the logging duration.
+ optional int64 radio_background_scan_time_ms = 7;
+
+ // Total time the wifi radio spent doing roam scans in ms over the logging duration.
+ optional int64 radio_roam_scan_time_ms = 8;
+
+ // Total time the wifi radio spent doing pno scans in ms over the logging duration.
+ optional int64 radio_pno_scan_time_ms = 9;
+
+ // Total time the wifi radio spent doing hotspot 2.0 scans and GAS exchange
+ // in ms over the logging duration.
+ optional int64 radio_hs20_scan_time_ms = 10;
} \ No newline at end of file
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 4205ac7d9f86..31238df6ea10 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -166,12 +166,12 @@ public final class AutofillManagerService
context.registerReceiver(mBroadcastReceiver, filter, null, FgThread.getHandler());
}
- @Override // from MasterSystemService
+ @Override // from AbstractMasterSystemService
protected String getServiceSettingsProperty() {
return Settings.Secure.AUTOFILL_SERVICE;
}
- @Override // from MasterSystemService
+ @Override // from AbstractMasterSystemService
protected void registerForExtraSettingsChanges(@NonNull ContentResolver resolver,
@NonNull ContentObserver observer) {
resolver.registerContentObserver(Settings.Global.getUriFor(
@@ -188,7 +188,7 @@ public final class AutofillManagerService
UserHandle.USER_ALL);
}
- @Override // from MasterSystemService
+ @Override // from AbstractMasterSystemService
protected void onSettingsChanged(int userId, @NonNull String property) {
switch (property) {
case Settings.Global.AUTOFILL_LOGGING_LEVEL:
@@ -210,25 +210,24 @@ public final class AutofillManagerService
}
}
- @Override // from MasterSystemService
- protected AutofillManagerServiceImpl newServiceLocked(int resolvedUserId, boolean disabled) {
+ @Override // from AbstractMasterSystemService
+ protected AutofillManagerServiceImpl newServiceLocked(@UserIdInt int resolvedUserId,
+ boolean disabled) {
return new AutofillManagerServiceImpl(this, mLock, mRequestsHistory,
mUiLatencyHistory, mWtfHistory, resolvedUserId, mUi, mAutofillCompatState,
disabled);
}
- @Override // MasterSystemService
- protected AutofillManagerServiceImpl removeCachedServiceLocked(int userId) {
- final AutofillManagerServiceImpl service = super.removeCachedServiceLocked(userId);
- if (service != null) {
- service.destroyLocked();
- mAutofillCompatState.removeCompatibilityModeRequests(userId);
- }
- return service;
+ @Override // AbstractMasterSystemService
+ protected void onServiceRemoved(@NonNull AutofillManagerServiceImpl service,
+ @UserIdInt int userId) {
+ service.destroyLocked();
+ mAutofillCompatState.removeCompatibilityModeRequests(userId);
}
- @Override // from MasterSystemService
- protected void onServiceEnabledLocked(@NonNull AutofillManagerServiceImpl service, int userId) {
+ @Override // from AbstractMasterSystemService
+ protected void onServiceEnabledLocked(@NonNull AutofillManagerServiceImpl service,
+ @UserIdInt int userId) {
addCompatibilityModeRequestsLocked(service, userId);
}
@@ -245,7 +244,7 @@ public final class AutofillManagerService
}
// Called by Shell command.
- void destroySessions(int userId, IResultReceiver receiver) {
+ void destroySessions(@UserIdInt int userId, IResultReceiver receiver) {
Slog.i(TAG, "destroySessions() for userId " + userId);
getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 1ad83ecb1237..c12a5e7f727a 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -104,7 +104,6 @@ import com.android.server.SystemService;
import com.android.server.backup.fullbackup.FullBackupEntry;
import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
import com.android.server.backup.internal.BackupHandler;
-import com.android.server.backup.keyvalue.BackupRequest;
import com.android.server.backup.internal.ClearDataObserver;
import com.android.server.backup.internal.OnTaskFinishedListener;
import com.android.server.backup.internal.Operation;
@@ -112,6 +111,7 @@ import com.android.server.backup.internal.PerformInitializeTask;
import com.android.server.backup.internal.ProvisionedObserver;
import com.android.server.backup.internal.RunBackupReceiver;
import com.android.server.backup.internal.RunInitializeReceiver;
+import com.android.server.backup.keyvalue.BackupRequest;
import com.android.server.backup.params.AdbBackupParams;
import com.android.server.backup.params.AdbParams;
import com.android.server.backup.params.AdbRestoreParams;
@@ -160,7 +160,6 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
public class BackupManagerService {
-
public static final String TAG = "BackupManagerService";
public static final boolean DEBUG = true;
public static final boolean MORE_DEBUG = false;
@@ -170,6 +169,9 @@ public class BackupManagerService {
// nonzero == enabled. File missing or contains a zero byte == disabled.
private static final String BACKUP_ENABLE_FILE = "backup_enabled";
+ // Persistently track the need to do a full init.
+ private static final String INIT_SENTINEL_FILE_NAME = "_need_init_";
+
// System-private key used for backing up an app's widget state. Must
// begin with U+FFxx by convention (we reserve all keys starting
// with U+FF00 or higher for system use).
@@ -196,11 +198,16 @@ public class BackupManagerService {
public static final int BACKUP_METADATA_VERSION = 1;
public static final int BACKUP_WIDGET_METADATA_TOKEN = 0x01FFED01;
- private static final boolean COMPRESS_FULL_BACKUPS = true; // should be true in production
+ private static final int CURRENT_ANCESTRAL_RECORD_VERSION = 1;
+
+ // Round-robin queue for scheduling full backup passes.
+ private static final int SCHEDULE_FILE_VERSION = 1;
public static final String SETTINGS_PACKAGE = "com.android.providers.settings";
public static final String SHARED_BACKUP_AGENT_PACKAGE = "com.android.sharedstoragebackup";
- private static final String SERVICE_ACTION_TRANSPORT_HOST = "android.backup.TRANSPORT_HOST";
+
+ // Pseudoname that we use for the Package Manager metadata "package".
+ public static final String PACKAGE_MANAGER_SENTINEL = "@pm@";
// Retry interval for clear/init when the transport is unavailable
private static final long TRANSPORT_RETRY_INTERVAL = 1 * AlarmManager.INTERVAL_HOUR;
@@ -210,6 +217,21 @@ public class BackupManagerService {
public static final String BACKUP_FINISHED_ACTION = "android.intent.action.BACKUP_FINISHED";
public static final String BACKUP_FINISHED_PACKAGE_EXTRA = "packageName";
+ // Bookkeeping of in-flight operations. The operation token is the index of the entry in the
+ // pending operations list.
+ public static final int OP_PENDING = 0;
+ private static final int OP_ACKNOWLEDGED = 1;
+ private static final int OP_TIMEOUT = -1;
+
+ // Waiting for backup agent to respond during backup operation.
+ public static final int OP_TYPE_BACKUP_WAIT = 0;
+
+ // Waiting for backup agent to respond during restore operation.
+ public static final int OP_TYPE_RESTORE_WAIT = 1;
+
+ // An entire backup operation spanning multiple packages.
+ public static final int OP_TYPE_BACKUP = 2;
+
// Time delay for initialization operations that can be delayed so as not to consume too much CPU
// on bring-up and increase time-to-UI.
private static final long INITIALIZATION_DELAY_MILLIS = 3000;
@@ -226,8 +248,62 @@ public class BackupManagerService {
private static final long BUSY_BACKOFF_MIN_MILLIS = 1000 * 60 * 60; // one hour
private static final int BUSY_BACKOFF_FUZZ = 1000 * 60 * 60 * 2; // two hours
- private BackupManagerConstants mConstants;
+ // The published binder is a singleton Trampoline object that calls through to the proper code.
+ // This indirection lets us turn down the heavy implementation object on the fly without
+ // disturbing binders that have been cached elsewhere in the system.
+ private static Trampoline sInstance;
+
+ static Trampoline getInstance() {
+ // Always constructed during system bring up, so no need to lazy-init.
+ return sInstance;
+ }
+
+ /** Helper to create the {@link BackupManagerService} instance. */
+ public static BackupManagerService create(
+ Context context,
+ Trampoline parent,
+ HandlerThread backupThread) {
+ // Set up our transport options and initialize the default transport
+ SystemConfig systemConfig = SystemConfig.getInstance();
+ Set<ComponentName> transportWhitelist = systemConfig.getBackupTransportWhitelist();
+ if (transportWhitelist == null) {
+ transportWhitelist = Collections.emptySet();
+ }
+
+ String transport =
+ Settings.Secure.getString(
+ context.getContentResolver(), Settings.Secure.BACKUP_TRANSPORT);
+ if (TextUtils.isEmpty(transport)) {
+ transport = null;
+ }
+ if (DEBUG) {
+ Slog.v(TAG, "Starting with transport " + transport);
+ }
+ TransportManager transportManager =
+ new TransportManager(
+ context,
+ transportWhitelist,
+ transport);
+
+ // If encrypted file systems is enabled or disabled, this call will return the
+ // correct directory.
+ File baseStateDir = new File(Environment.getDataDirectory(), "backup");
+
+ // This dir on /cache is managed directly in init.rc
+ File dataDir = new File(Environment.getDownloadCacheDirectory(), "backup_stage");
+
+ return new BackupManagerService(
+ context,
+ parent,
+ backupThread,
+ baseStateDir,
+ dataDir,
+ transportManager);
+ }
+
private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
+ private final TransportManager mTransportManager;
+
private Context mContext;
private PackageManager mPackageManager;
private IPackageManager mPackageManagerBinder;
@@ -235,20 +311,21 @@ public class BackupManagerService {
private PowerManager mPowerManager;
private AlarmManager mAlarmManager;
private IStorageManager mStorageManager;
+ private BackupManagerConstants mConstants;
+ private PowerManager.WakeLock mWakelock;
+ private BackupHandler mBackupHandler;
private IBackupManager mBackupManagerBinder;
- private final TransportManager mTransportManager;
-
private boolean mEnabled; // access to this is synchronized on 'this'
private boolean mProvisioned;
private boolean mAutoRestore;
- private PowerManager.WakeLock mWakelock;
- private BackupHandler mBackupHandler;
+
private PendingIntent mRunBackupIntent;
private PendingIntent mRunInitIntent;
- private BroadcastReceiver mRunBackupReceiver;
- private BroadcastReceiver mRunInitReceiver;
+
+ private final ArraySet<String> mPendingInits = new ArraySet<>(); // transport names
+
// map UIDs to the set of participating packages under that UID
private final SparseArray<HashSet<String>> mBackupParticipants
= new SparseArray<>();
@@ -257,9 +334,6 @@ public class BackupManagerService {
private HashMap<String, BackupRequest> mPendingBackups
= new HashMap<>();
- // Pseudoname that we use for the Package Manager metadata "package"
- public static final String PACKAGE_MANAGER_SENTINEL = "@pm@";
-
// locking around the pending-backup management
private final Object mQueueLock = new Object();
@@ -269,25 +343,32 @@ public class BackupManagerService {
// completed.
private final Object mAgentConnectLock = new Object();
private IBackupAgent mConnectedAgent;
- private volatile boolean mBackupRunning;
private volatile boolean mConnecting;
- private volatile long mLastBackupPass;
- // For debugging, we maintain a progress trace of operations during backup
- public static final boolean DEBUG_BACKUP_TRACE = true;
- private final List<String> mBackupTrace = new ArrayList<>();
+ private volatile boolean mBackupRunning;
+ private volatile long mLastBackupPass;
// A similar synchronization mechanism around clearing apps' data for restore
private final Object mClearDataLock = new Object();
private volatile boolean mClearingData;
+ // Used by ADB.
private final BackupPasswordManager mBackupPasswordManager;
+ private final SparseArray<AdbParams> mAdbBackupRestoreConfirmations = new SparseArray<>();
+ private final SecureRandom mRng = new SecureRandom();
// Time when we post the transport registration operation
private final long mRegisterTransportsRequestedTime;
+ @GuardedBy("mQueueLock")
+ private PerformFullTransportBackupTask mRunningFullBackupTask;
+
+ @GuardedBy("mQueueLock")
+ private ArrayList<FullBackupEntry> mFullBackupQueue;
+
@GuardedBy("mPendingRestores")
private boolean mIsRestoreInProgress;
+
@GuardedBy("mPendingRestores")
private final Queue<PerformUnifiedRestoreTask> mPendingRestores = new ArrayDeque<>();
@@ -296,17 +377,155 @@ public class BackupManagerService {
// Watch the device provisioning operation during setup
private ContentObserver mProvisionedObserver;
- // The published binder is actually to a singleton trampoline object that calls
- // through to the proper code. This indirection lets us turn down the heavy
- // implementation object on the fly without disturbing binders that have been
- // cached elsewhere in the system.
- static Trampoline sInstance;
+ /**
+ * mCurrentOperations contains the list of currently active operations.
+ *
+ * If type of operation is OP_TYPE_WAIT, it are waiting for an ack or timeout.
+ * An operation wraps a BackupRestoreTask within it.
+ * It's the responsibility of this task to remove the operation from this array.
+ *
+ * A BackupRestore task gets notified of ack/timeout for the operation via
+ * BackupRestoreTask#handleCancel, BackupRestoreTask#operationComplete and notifyAll called
+ * on the mCurrentOpLock.
+ * {@link BackupManagerService#waitUntilOperationComplete(int)} is
+ * used in various places to 'wait' for notifyAll and detect change of pending state of an
+ * operation. So typically, an operation will be removed from this array by:
+ * - BackupRestoreTask#handleCancel and
+ * - BackupRestoreTask#operationComplete OR waitUntilOperationComplete. Do not remove at both
+ * these places because waitUntilOperationComplete relies on the operation being present to
+ * determine its completion status.
+ *
+ * If type of operation is OP_BACKUP, it is a task running backups. It provides a handle to
+ * cancel backup tasks.
+ */
+ @GuardedBy("mCurrentOpLock")
+ private final SparseArray<Operation> mCurrentOperations = new SparseArray<>();
+ private final Object mCurrentOpLock = new Object();
+ private final Random mTokenGenerator = new Random();
+ final AtomicInteger mNextToken = new AtomicInteger();
+
+ // Where we keep our journal files and other bookkeeping.
+ private File mBaseStateDir;
+ private File mDataDir;
+ private File mJournalDir;
+ @Nullable
+ private DataChangedJournal mJournal;
+ private File mFullBackupScheduleFile;
- static Trampoline getInstance() {
- // Always constructed during system bringup, so no need to lazy-init
- return sInstance;
+ // Keep a log of all the apps we've ever backed up.
+ private ProcessedPackagesJournal mProcessedPackagesJournal;
+
+ private File mTokenFile;
+ private Set<String> mAncestralPackages = null;
+ private long mAncestralToken = 0;
+ private long mCurrentToken = 0;
+
+ @VisibleForTesting
+ public BackupManagerService(
+ Context context,
+ Trampoline parent,
+ HandlerThread backupThread,
+ File baseStateDir,
+ File dataDir,
+ TransportManager transportManager) {
+ mContext = context;
+ mPackageManager = context.getPackageManager();
+ mPackageManagerBinder = AppGlobals.getPackageManager();
+ mActivityManager = ActivityManager.getService();
+
+ mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mStorageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
+
+ mBackupManagerBinder = Trampoline.asInterface(parent.asBinder());
+
+ mAgentTimeoutParameters = new
+ BackupAgentTimeoutParameters(Handler.getMain(), mContext.getContentResolver());
+ mAgentTimeoutParameters.start();
+
+ // spin up the backup/restore handler thread
+ mBackupHandler = new BackupHandler(this, backupThread.getLooper());
+
+ // Set up our bookkeeping
+ final ContentResolver resolver = context.getContentResolver();
+ mProvisioned = Settings.Global.getInt(resolver,
+ Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+ mAutoRestore = Settings.Secure.getInt(resolver,
+ Settings.Secure.BACKUP_AUTO_RESTORE, 1) != 0;
+
+ mProvisionedObserver = new ProvisionedObserver(this, mBackupHandler);
+ resolver.registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
+ false, mProvisionedObserver);
+
+ mBaseStateDir = baseStateDir;
+ mBaseStateDir.mkdirs();
+ if (!SELinux.restorecon(mBaseStateDir)) {
+ Slog.e(TAG, "SELinux restorecon failed on " + mBaseStateDir);
+ }
+
+ mDataDir = dataDir;
+
+ mBackupPasswordManager = new BackupPasswordManager(mContext, mBaseStateDir, mRng);
+
+ // Alarm receivers for scheduled backups & initialization operations
+ BroadcastReceiver mRunBackupReceiver = new RunBackupReceiver(this);
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(RUN_BACKUP_ACTION);
+ context.registerReceiver(mRunBackupReceiver, filter,
+ android.Manifest.permission.BACKUP, null);
+
+ BroadcastReceiver mRunInitReceiver = new RunInitializeReceiver(this);
+ filter = new IntentFilter();
+ filter.addAction(RUN_INITIALIZE_ACTION);
+ context.registerReceiver(mRunInitReceiver, filter,
+ android.Manifest.permission.BACKUP, null);
+
+ Intent backupIntent = new Intent(RUN_BACKUP_ACTION);
+ backupIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ mRunBackupIntent = PendingIntent.getBroadcast(context, 0, backupIntent, 0);
+
+ Intent initIntent = new Intent(RUN_INITIALIZE_ACTION);
+ initIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ mRunInitIntent = PendingIntent.getBroadcast(context, 0, initIntent, 0);
+
+ // Set up the backup-request journaling
+ mJournalDir = new File(mBaseStateDir, "pending");
+ mJournalDir.mkdirs(); // creates mBaseStateDir along the way
+ mJournal = null; // will be created on first use
+
+ mConstants = new BackupManagerConstants(mBackupHandler, mContext.getContentResolver());
+ // We are observing changes to the constants throughout the lifecycle of BMS. This is
+ // because we reference the constants in multiple areas of BMS, which otherwise would
+ // require frequent starting and stopping.
+ mConstants.start();
+
+ // Set up the various sorts of package tracking we do
+ mFullBackupScheduleFile = new File(mBaseStateDir, "fb-schedule");
+ initPackageTracking();
+
+ // Build our mapping of uid to backup client services. This implicitly
+ // schedules a backup pass on the Package Manager metadata the first
+ // time anything needs to be backed up.
+ synchronized (mBackupParticipants) {
+ addPackageParticipantsLocked(null);
+ }
+
+ mTransportManager = transportManager;
+ mTransportManager.setOnTransportRegisteredListener(this::onTransportRegistered);
+ mRegisterTransportsRequestedTime = SystemClock.elapsedRealtime();
+ mBackupHandler.postDelayed(
+ mTransportManager::registerTransports, INITIALIZATION_DELAY_MILLIS);
+
+ // Now that we know about valid backup participants, parse any leftover journal files into
+ // the pending backup set
+ mBackupHandler.postDelayed(this::parseLeftoverJournals, INITIALIZATION_DELAY_MILLIS);
+
+ // Power management
+ mWakelock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*");
}
+
public BackupManagerConstants getConstants() {
return mConstants;
}
@@ -549,6 +768,7 @@ public class BackupManagerService {
return mPendingInits;
}
+ /** Clear all pending transport initializations. */
public void clearPendingInits() {
mPendingInits.clear();
}
@@ -562,28 +782,10 @@ public class BackupManagerService {
mRunningFullBackupTask = runningFullBackupTask;
}
- public static final class Lifecycle extends SystemService {
-
- public Lifecycle(Context context) {
- super(context);
- sInstance = new Trampoline(context);
- }
-
- @Override
- public void onStart() {
- publishBinderService(Context.BACKUP_SERVICE, sInstance);
- }
-
- @Override
- public void onUnlockUser(int userId) {
- if (userId == UserHandle.USER_SYSTEM) {
- sInstance.unlockSystemUser();
- }
- }
- }
-
- // Called through the trampoline from onUnlockUser(), then we buck the work
- // off to the background thread to keep the unlock time down.
+ /**
+ * Called through Trampoline from {@link Lifecycle#onUnlockUser(int)}. We run the heavy work on
+ * a background thread to keep the unlock time down.
+ */
public void unlockSystemUser() {
// Migrate legacy setting
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup migrate");
@@ -618,89 +820,10 @@ public class BackupManagerService {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
- // Bookkeeping of in-flight operations for timeout etc. purposes. The operation
- // token is the index of the entry in the pending-operations list.
- public static final int OP_PENDING = 0;
- private static final int OP_ACKNOWLEDGED = 1;
- private static final int OP_TIMEOUT = -1;
-
- // Waiting for backup agent to respond during backup operation.
- public static final int OP_TYPE_BACKUP_WAIT = 0;
-
- // Waiting for backup agent to respond during restore operation.
- public static final int OP_TYPE_RESTORE_WAIT = 1;
-
- // An entire backup operation spanning multiple packages.
- public static final int OP_TYPE_BACKUP = 2;
-
/**
- * mCurrentOperations contains the list of currently active operations.
- *
- * If type of operation is OP_TYPE_WAIT, it are waiting for an ack or timeout.
- * An operation wraps a BackupRestoreTask within it.
- * It's the responsibility of this task to remove the operation from this array.
- *
- * A BackupRestore task gets notified of ack/timeout for the operation via
- * BackupRestoreTask#handleCancel, BackupRestoreTask#operationComplete and notifyAll called
- * on the mCurrentOpLock.
- * {@link BackupManagerService#waitUntilOperationComplete(int)} is
- * used in various places to 'wait' for notifyAll and detect change of pending state of an
- * operation. So typically, an operation will be removed from this array by:
- * - BackupRestoreTask#handleCancel and
- * - BackupRestoreTask#operationComplete OR waitUntilOperationComplete. Do not remove at both
- * these places because waitUntilOperationComplete relies on the operation being present to
- * determine its completion status.
- *
- * If type of operation is OP_BACKUP, it is a task running backups. It provides a handle to
- * cancel backup tasks.
+ * Utility: build a new random integer token. The low bits are the ordinal of the operation for
+ * near-time uniqueness, and the upper bits are random for app-side unpredictability.
*/
- @GuardedBy("mCurrentOpLock")
- private final SparseArray<Operation> mCurrentOperations = new SparseArray<>();
- private final Object mCurrentOpLock = new Object();
- private final Random mTokenGenerator = new Random();
- final AtomicInteger mNextToken = new AtomicInteger();
-
- private final SparseArray<AdbParams> mAdbBackupRestoreConfirmations = new SparseArray<>();
-
- // Where we keep our journal files and other bookkeeping
- private File mBaseStateDir;
- private File mDataDir;
- private File mJournalDir;
- @Nullable
- private DataChangedJournal mJournal;
-
- private final SecureRandom mRng = new SecureRandom();
-
- // Keep a log of all the apps we've ever backed up, and what the dataset tokens are for both
- // the current backup dataset and the ancestral dataset.
- private ProcessedPackagesJournal mProcessedPackagesJournal;
-
- private static final int CURRENT_ANCESTRAL_RECORD_VERSION = 1;
- // increment when the schema changes
- private File mTokenFile;
- private Set<String> mAncestralPackages = null;
- private long mAncestralToken = 0;
- private long mCurrentToken = 0;
-
- // Persistently track the need to do a full init
- private static final String INIT_SENTINEL_FILE_NAME = "_need_init_";
- private final ArraySet<String> mPendingInits = new ArraySet<>(); // transport names
-
- // Round-robin queue for scheduling full backup passes
- private static final int SCHEDULE_FILE_VERSION = 1; // current version of the schedule file
-
- private File mFullBackupScheduleFile;
- // If we're running a schedule-driven full backup, this is the task instance doing it
-
- @GuardedBy("mQueueLock")
- private PerformFullTransportBackupTask mRunningFullBackupTask;
-
- @GuardedBy("mQueueLock")
- private ArrayList<FullBackupEntry> mFullBackupQueue;
-
- // Utility: build a new random integer token. The low bits are the ordinal of the
- // operation for near-time uniqueness, and the upper bits are random for app-
- // side unpredictability.
public int generateRandomIntegerToken() {
int token = mTokenGenerator.nextInt();
if (token < 0) token = -token;
@@ -709,10 +832,9 @@ public class BackupManagerService {
return token;
}
- /*
- * Construct a backup agent instance for the metadata pseudopackage. This is a
- * process-local non-lifecycle agent instance, so we manually set up the context
- * topology for it.
+ /**
+ * Construct a backup agent instance for the metadata pseudopackage. This is a process-local
+ * non-lifecycle agent instance, so we manually set up the context topology for it.
*/
public BackupAgent makeMetadataAgent() {
PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(mPackageManager);
@@ -721,8 +843,8 @@ public class BackupManagerService {
return pmAgent;
}
- /*
- * Same as above but with the explicit package-set configuration.
+ /**
+ * Same as {@link #makeMetadataAgent()} but with explicit package-set configuration.
*/
public PackageManagerBackupAgent makeMetadataAgent(List<PackageInfo> packages) {
PackageManagerBackupAgent pmAgent =
@@ -732,172 +854,6 @@ public class BackupManagerService {
return pmAgent;
}
- // ----- Debug-only backup operation trace -----
- public void addBackupTrace(String s) {
- if (DEBUG_BACKUP_TRACE) {
- synchronized (mBackupTrace) {
- mBackupTrace.add(s);
- }
- }
- }
-
- public void clearBackupTrace() {
- if (DEBUG_BACKUP_TRACE) {
- synchronized (mBackupTrace) {
- mBackupTrace.clear();
- }
- }
- }
-
- // ----- Main service implementation -----
-
- public static BackupManagerService create(
- Context context,
- Trampoline parent,
- HandlerThread backupThread) {
- // Set up our transport options and initialize the default transport
- SystemConfig systemConfig = SystemConfig.getInstance();
- Set<ComponentName> transportWhitelist = systemConfig.getBackupTransportWhitelist();
- if (transportWhitelist == null) {
- transportWhitelist = Collections.emptySet();
- }
-
- String transport =
- Settings.Secure.getString(
- context.getContentResolver(), Settings.Secure.BACKUP_TRANSPORT);
- if (TextUtils.isEmpty(transport)) {
- transport = null;
- }
- if (DEBUG) {
- Slog.v(TAG, "Starting with transport " + transport);
- }
- TransportManager transportManager =
- new TransportManager(
- context,
- transportWhitelist,
- transport);
-
- // If encrypted file systems is enabled or disabled, this call will return the
- // correct directory.
- File baseStateDir = new File(Environment.getDataDirectory(), "backup");
-
- // This dir on /cache is managed directly in init.rc
- File dataDir = new File(Environment.getDownloadCacheDirectory(), "backup_stage");
-
- return new BackupManagerService(
- context,
- parent,
- backupThread,
- baseStateDir,
- dataDir,
- transportManager);
- }
-
- @VisibleForTesting
- public BackupManagerService(
- Context context,
- Trampoline parent,
- HandlerThread backupThread,
- File baseStateDir,
- File dataDir,
- TransportManager transportManager) {
- mContext = context;
- mPackageManager = context.getPackageManager();
- mPackageManagerBinder = AppGlobals.getPackageManager();
- mActivityManager = ActivityManager.getService();
-
- mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- mStorageManager = IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
-
- mBackupManagerBinder = Trampoline.asInterface(parent.asBinder());
-
- mAgentTimeoutParameters = new
- BackupAgentTimeoutParameters(Handler.getMain(), mContext.getContentResolver());
- mAgentTimeoutParameters.start();
-
- // spin up the backup/restore handler thread
- mBackupHandler = new BackupHandler(this, backupThread.getLooper());
-
- // Set up our bookkeeping
- final ContentResolver resolver = context.getContentResolver();
- mProvisioned = Settings.Global.getInt(resolver,
- Settings.Global.DEVICE_PROVISIONED, 0) != 0;
- mAutoRestore = Settings.Secure.getInt(resolver,
- Settings.Secure.BACKUP_AUTO_RESTORE, 1) != 0;
-
- mProvisionedObserver = new ProvisionedObserver(this, mBackupHandler);
- resolver.registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
- false, mProvisionedObserver);
-
- mBaseStateDir = baseStateDir;
- mBaseStateDir.mkdirs();
- if (!SELinux.restorecon(mBaseStateDir)) {
- Slog.e(TAG, "SELinux restorecon failed on " + mBaseStateDir);
- }
-
- mDataDir = dataDir;
-
- mBackupPasswordManager = new BackupPasswordManager(mContext, mBaseStateDir, mRng);
-
- // Alarm receivers for scheduled backups & initialization operations
- mRunBackupReceiver = new RunBackupReceiver(this);
- IntentFilter filter = new IntentFilter();
- filter.addAction(RUN_BACKUP_ACTION);
- context.registerReceiver(mRunBackupReceiver, filter,
- android.Manifest.permission.BACKUP, null);
-
- mRunInitReceiver = new RunInitializeReceiver(this);
- filter = new IntentFilter();
- filter.addAction(RUN_INITIALIZE_ACTION);
- context.registerReceiver(mRunInitReceiver, filter,
- android.Manifest.permission.BACKUP, null);
-
- Intent backupIntent = new Intent(RUN_BACKUP_ACTION);
- backupIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- mRunBackupIntent = PendingIntent.getBroadcast(context, 0, backupIntent, 0);
-
- Intent initIntent = new Intent(RUN_INITIALIZE_ACTION);
- initIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- mRunInitIntent = PendingIntent.getBroadcast(context, 0, initIntent, 0);
-
- // Set up the backup-request journaling
- mJournalDir = new File(mBaseStateDir, "pending");
- mJournalDir.mkdirs(); // creates mBaseStateDir along the way
- mJournal = null; // will be created on first use
-
- mConstants = new BackupManagerConstants(mBackupHandler, mContext.getContentResolver());
- // We are observing changes to the constants throughout the lifecycle of BMS. This is
- // because we reference the constants in multiple areas of BMS, which otherwise would
- // require frequent starting and stopping.
- mConstants.start();
-
- // Set up the various sorts of package tracking we do
- mFullBackupScheduleFile = new File(mBaseStateDir, "fb-schedule");
- initPackageTracking();
-
- // Build our mapping of uid to backup client services. This implicitly
- // schedules a backup pass on the Package Manager metadata the first
- // time anything needs to be backed up.
- synchronized (mBackupParticipants) {
- addPackageParticipantsLocked(null);
- }
-
- mTransportManager = transportManager;
- mTransportManager.setOnTransportRegisteredListener(this::onTransportRegistered);
- mRegisterTransportsRequestedTime = SystemClock.elapsedRealtime();
- mBackupHandler.postDelayed(
- mTransportManager::registerTransports, INITIALIZATION_DELAY_MILLIS);
-
- // Now that we know about valid backup participants, parse any leftover journal files into
- // the pending backup set
- mBackupHandler.postDelayed(this::parseLeftoverJournals, INITIALIZATION_DELAY_MILLIS);
-
- // Power management
- mWakelock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*");
- }
-
private void initPackageTracking() {
if (MORE_DEBUG) Slog.v(TAG, "` tracking");
@@ -2750,54 +2706,6 @@ public class BackupManagerService {
}
}
- private static boolean backupSettingMigrated(int userId) {
- File base = new File(Environment.getDataDirectory(), "backup");
- File enableFile = new File(base, BACKUP_ENABLE_FILE);
- return enableFile.exists();
- }
-
- private static boolean readBackupEnableState(int userId) {
- File base = new File(Environment.getDataDirectory(), "backup");
- File enableFile = new File(base, BACKUP_ENABLE_FILE);
- if (enableFile.exists()) {
- try (FileInputStream fin = new FileInputStream(enableFile)) {
- int state = fin.read();
- return state != 0;
- } catch (IOException e) {
- // can't read the file; fall through to assume disabled
- Slog.e(TAG, "Cannot read enable state; assuming disabled");
- }
- } else {
- if (DEBUG) {
- Slog.i(TAG, "isBackupEnabled() => false due to absent settings file");
- }
- }
- return false;
- }
-
- private static void writeBackupEnableState(boolean enable, int userId) {
- File base = new File(Environment.getDataDirectory(), "backup");
- File enableFile = new File(base, BACKUP_ENABLE_FILE);
- File stage = new File(base, BACKUP_ENABLE_FILE + "-stage");
- try (FileOutputStream fout = new FileOutputStream(stage)) {
- fout.write(enable ? 1 : 0);
- fout.close();
- stage.renameTo(enableFile);
- // will be synced immediately by the try-with-resources call to close()
- } catch (IOException | RuntimeException e) {
- // Whoops; looks like we're doomed. Roll everything out, disabled,
- // including the legacy state.
- Slog.e(TAG, "Unable to record backup enable state; reverting to disabled: "
- + e.getMessage());
-
- ContentResolver resolver = sInstance.getContext().getContentResolver();
- Settings.Secure.putStringForUser(resolver,
- Settings.Secure.BACKUP_ENABLED, null, userId);
- enableFile.delete();
- stage.delete();
- }
- }
-
// Enable/disable backups
public void setBackupEnabled(boolean enable) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
@@ -3565,17 +3473,6 @@ public class BackupManagerService {
pw.println(" " + s);
}
- if (DEBUG_BACKUP_TRACE) {
- synchronized (mBackupTrace) {
- if (!mBackupTrace.isEmpty()) {
- pw.println("Most recent backup trace:");
- for (String s : mBackupTrace) {
- pw.println(" " + s);
- }
- }
- }
- }
-
pw.print("Ancestral: ");
pw.println(Long.toHexString(mAncestralToken));
pw.print("Current: ");
@@ -3627,4 +3524,71 @@ public class BackupManagerService {
return mBackupManagerBinder;
}
+ private static boolean backupSettingMigrated(int userId) {
+ File base = new File(Environment.getDataDirectory(), "backup");
+ File enableFile = new File(base, BACKUP_ENABLE_FILE);
+ return enableFile.exists();
+ }
+
+ private static boolean readBackupEnableState(int userId) {
+ File base = new File(Environment.getDataDirectory(), "backup");
+ File enableFile = new File(base, BACKUP_ENABLE_FILE);
+ if (enableFile.exists()) {
+ try (FileInputStream fin = new FileInputStream(enableFile)) {
+ int state = fin.read();
+ return state != 0;
+ } catch (IOException e) {
+ // can't read the file; fall through to assume disabled
+ Slog.e(TAG, "Cannot read enable state; assuming disabled");
+ }
+ } else {
+ if (DEBUG) {
+ Slog.i(TAG, "isBackupEnabled() => false due to absent settings file");
+ }
+ }
+ return false;
+ }
+
+ private static void writeBackupEnableState(boolean enable, int userId) {
+ File base = new File(Environment.getDataDirectory(), "backup");
+ File enableFile = new File(base, BACKUP_ENABLE_FILE);
+ File stage = new File(base, BACKUP_ENABLE_FILE + "-stage");
+ try (FileOutputStream fout = new FileOutputStream(stage)) {
+ fout.write(enable ? 1 : 0);
+ fout.close();
+ stage.renameTo(enableFile);
+ // will be synced immediately by the try-with-resources call to close()
+ } catch (IOException | RuntimeException e) {
+ // Whoops; looks like we're doomed. Roll everything out, disabled,
+ // including the legacy state.
+ Slog.e(TAG, "Unable to record backup enable state; reverting to disabled: "
+ + e.getMessage());
+
+ ContentResolver resolver = sInstance.getContext().getContentResolver();
+ Settings.Secure.putStringForUser(resolver,
+ Settings.Secure.BACKUP_ENABLED, null, userId);
+ enableFile.delete();
+ stage.delete();
+ }
+ }
+
+ /** Implementation to receive lifecycle event callbacks for system services. */
+ public static final class Lifecycle extends SystemService {
+ public Lifecycle(Context context) {
+ super(context);
+ sInstance = new Trampoline(context);
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.BACKUP_SERVICE, sInstance);
+ }
+
+ @Override
+ public void onUnlockUser(int userId) {
+ if (userId == UserHandle.USER_SYSTEM) {
+ sInstance.unlockSystemUser();
+ }
+ }
+ }
}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunker.java b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunker.java
new file mode 100644
index 000000000000..18011f620b24
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunker.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup.encryption.chunking.cdc;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import com.android.server.backup.encryption.chunking.Chunker;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.util.Arrays;
+
+/** Splits a stream of bytes into variable-sized chunks, using content-defined chunking. */
+public class ContentDefinedChunker implements Chunker {
+ private static final int WINDOW_SIZE = 31;
+ private static final byte DEFAULT_OUT_BYTE = (byte) 0;
+
+ private final byte[] mChunkBuffer;
+ private final RabinFingerprint64 mRabinFingerprint64;
+ private final FingerprintMixer mFingerprintMixer;
+ private final BreakpointPredicate mBreakpointPredicate;
+ private final int mMinChunkSize;
+ private final int mMaxChunkSize;
+
+ /**
+ * Constructor.
+ *
+ * @param minChunkSize The minimum size of a chunk. No chunk will be produced of a size smaller
+ * than this except possibly at the very end of the stream.
+ * @param maxChunkSize The maximum size of a chunk. No chunk will be produced of a larger size.
+ * @param rabinFingerprint64 Calculates fingerprints, with which to determine breakpoints.
+ * @param breakpointPredicate Given a Rabin fingerprint, returns whether this ought to be a
+ * breakpoint.
+ */
+ public ContentDefinedChunker(
+ int minChunkSize,
+ int maxChunkSize,
+ RabinFingerprint64 rabinFingerprint64,
+ FingerprintMixer fingerprintMixer,
+ BreakpointPredicate breakpointPredicate) {
+ checkArgument(
+ minChunkSize >= WINDOW_SIZE,
+ "Minimum chunk size must be greater than window size.");
+ checkArgument(
+ maxChunkSize >= minChunkSize,
+ "Maximum chunk size cannot be smaller than minimum chunk size.");
+ mChunkBuffer = new byte[maxChunkSize];
+ mRabinFingerprint64 = rabinFingerprint64;
+ mBreakpointPredicate = breakpointPredicate;
+ mFingerprintMixer = fingerprintMixer;
+ mMinChunkSize = minChunkSize;
+ mMaxChunkSize = maxChunkSize;
+ }
+
+ /**
+ * Breaks the input stream into variable-sized chunks.
+ *
+ * @param inputStream The input bytes to break into chunks.
+ * @param chunkConsumer A function to process each chunk as it's generated.
+ * @throws IOException Thrown if there is an issue reading from the input stream.
+ * @throws GeneralSecurityException Thrown if the {@link ChunkConsumer} throws it.
+ */
+ @Override
+ public void chunkify(InputStream inputStream, ChunkConsumer chunkConsumer)
+ throws IOException, GeneralSecurityException {
+ int chunkLength;
+ int initialReadLength = mMinChunkSize - WINDOW_SIZE;
+
+ // Performance optimization - there is no reason to calculate fingerprints for windows
+ // ending before the minimum chunk size.
+ while ((chunkLength =
+ inputStream.read(mChunkBuffer, /*off=*/ 0, /*len=*/ initialReadLength))
+ != -1) {
+ int b;
+ long fingerprint = 0L;
+
+ while ((b = inputStream.read()) != -1) {
+ byte inByte = (byte) b;
+ byte outByte = getCurrentWindowStartByte(chunkLength);
+ mChunkBuffer[chunkLength++] = inByte;
+
+ fingerprint =
+ mRabinFingerprint64.computeFingerprint64(inByte, outByte, fingerprint);
+
+ if (chunkLength >= mMaxChunkSize
+ || (chunkLength >= mMinChunkSize
+ && mBreakpointPredicate.isBreakpoint(
+ mFingerprintMixer.mix(fingerprint)))) {
+ chunkConsumer.accept(Arrays.copyOf(mChunkBuffer, chunkLength));
+ chunkLength = 0;
+ break;
+ }
+ }
+
+ if (chunkLength > 0) {
+ chunkConsumer.accept(Arrays.copyOf(mChunkBuffer, chunkLength));
+ }
+ }
+ }
+
+ private byte getCurrentWindowStartByte(int chunkLength) {
+ if (chunkLength < mMinChunkSize) {
+ return DEFAULT_OUT_BYTE;
+ } else {
+ return mChunkBuffer[chunkLength - WINDOW_SIZE];
+ }
+ }
+
+ /** Whether the current fingerprint indicates the end of a chunk. */
+ public interface BreakpointPredicate {
+
+ /**
+ * Returns {@code true} if the fingerprint of the last {@code WINDOW_SIZE} bytes indicates
+ * the chunk ought to end at this position.
+ *
+ * @param fingerprint Fingerprint of the last {@code WINDOW_SIZE} bytes.
+ * @return Whether this ought to be a chunk breakpoint.
+ */
+ boolean isBreakpoint(long fingerprint);
+ }
+}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/FingerprintMixer.java b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/FingerprintMixer.java
new file mode 100644
index 000000000000..e9f30505c112
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/FingerprintMixer.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup.encryption.chunking.cdc;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidKeyException;
+
+import javax.crypto.SecretKey;
+
+/**
+ * Helper for mixing fingerprint with key material.
+ *
+ * <p>We do this as otherwise the Rabin fingerprint leaks information about the plaintext. i.e., if
+ * two users have the same file, it will be partitioned by Rabin in the same way, allowing us to
+ * infer that it is the same as another user's file.
+ *
+ * <p>By mixing the fingerprint with the user's secret key, the chunking method is different on a
+ * per key basis. Each application has its own {@link SecretKey}, so we cannot infer that a file is
+ * the same even across multiple applications owned by the same user, never mind across multiple
+ * users.
+ *
+ * <p>Instead of directly mixing the fingerprint with the user's secret, we first securely and
+ * deterministically derive a secondary chunking key. As Rabin is not a cryptographically secure
+ * hash, it might otherwise leak information about the user's secret. This prevents that from
+ * happening.
+ */
+public class FingerprintMixer {
+ public static final int SALT_LENGTH_BYTES = 256 / Byte.SIZE;
+ private static final String DERIVED_KEY_NAME = "RabinFingerprint64Mixer";
+
+ private final long mAddend;
+ private final long mMultiplicand;
+
+ /**
+ * A new instance from a given secret key and salt. Salt must be the same across incremental
+ * backups, or a different chunking strategy will be used each time, defeating the dedup.
+ *
+ * @param secretKey The application-specific secret.
+ * @param salt The salt.
+ * @throws InvalidKeyException If the encoded form of {@code secretKey} is inaccessible.
+ */
+ public FingerprintMixer(SecretKey secretKey, byte[] salt) throws InvalidKeyException {
+ checkArgument(salt.length == SALT_LENGTH_BYTES, "Requires a 256-bit salt.");
+ byte[] keyBytes = secretKey.getEncoded();
+ if (keyBytes == null) {
+ throw new InvalidKeyException("SecretKey must support encoding for FingerprintMixer.");
+ }
+ byte[] derivedKey =
+ Hkdf.hkdf(keyBytes, salt, DERIVED_KEY_NAME.getBytes(StandardCharsets.UTF_8));
+ ByteBuffer buffer = ByteBuffer.wrap(derivedKey);
+ mAddend = buffer.getLong();
+ // Multiplicand must be odd - otherwise we lose some bits of the Rabin fingerprint when
+ // mixing
+ mMultiplicand = buffer.getLong() | 1;
+ }
+
+ /**
+ * Mixes the fingerprint with the derived key material. This is performed by adding part of the
+ * derived key and multiplying by another part of the derived key (which is forced to be odd, so
+ * that the operation is reversible).
+ *
+ * @param fingerprint A 64-bit Rabin fingerprint.
+ * @return The mixed fingerprint.
+ */
+ long mix(long fingerprint) {
+ return ((fingerprint + mAddend) * mMultiplicand);
+ }
+
+ /** The addend part of the derived key. */
+ long getAddend() {
+ return mAddend;
+ }
+
+ /** The multiplicand part of the derived key. */
+ long getMultiplicand() {
+ return mMultiplicand;
+ }
+}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/Hkdf.java b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/Hkdf.java
new file mode 100644
index 000000000000..6f4f549ab2d7
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/Hkdf.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup.encryption.chunking.cdc;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Secure HKDF utils. Allows client to deterministically derive additional key material from a base
+ * secret. If the derived key material is compromised, this does not in of itself compromise the
+ * root secret.
+ *
+ * <p>TODO(b/116575321): After all code is ported, rename this class to HkdfUtils.
+ */
+public final class Hkdf {
+ private static final byte[] CONSTANT_01 = {0x01};
+ private static final String HmacSHA256 = "HmacSHA256";
+ private static final String AES = "AES";
+
+ /**
+ * Implements HKDF (RFC 5869) with the SHA-256 hash and a 256-bit output key length.
+ *
+ * <p>IMPORTANT: The use or edit of this method requires a security review.
+ *
+ * @param masterKey Master key from which to derive sub-keys.
+ * @param salt A randomly generated 256-bit byte string.
+ * @param data Arbitrary information that is bound to the derived key (i.e., used in its
+ * creation).
+ * @return Raw derived key bytes = HKDF-SHA256(masterKey, salt, data).
+ * @throws InvalidKeyException If the salt can not be used as a valid key.
+ */
+ static byte[] hkdf(byte[] masterKey, byte[] salt, byte[] data) throws InvalidKeyException {
+ checkNotNull(masterKey, "HKDF requires master key to be set.");
+ checkNotNull(salt, "HKDF requires a salt.");
+ checkNotNull(data, "No data provided to HKDF.");
+ return hkdfSha256Expand(hkdfSha256Extract(masterKey, salt), data);
+ }
+
+ private Hkdf() {}
+
+ /**
+ * The HKDF (RFC 5869) extraction function, using the SHA-256 hash function. This function is
+ * used to pre-process the {@code inputKeyMaterial} and mix it with the {@code salt}, producing
+ * output suitable for use with HKDF expansion function (which produces the actual derived key).
+ *
+ * <p>IMPORTANT: The use or edit of this method requires a security review.
+ *
+ * @see #hkdfSha256Expand(byte[], byte[])
+ * @return HMAC-SHA256(salt, inputKeyMaterial) (salt is the "key" for the HMAC)
+ * @throws InvalidKeyException If the salt can not be used as a valid key.
+ */
+ private static byte[] hkdfSha256Extract(byte[] inputKeyMaterial, byte[] salt)
+ throws InvalidKeyException {
+ // Note that the SecretKey encoding format is defined to be RAW, so the encoded form should
+ // be consistent across implementations.
+ Mac sha256;
+ try {
+ sha256 = Mac.getInstance(HmacSHA256);
+ } catch (NoSuchAlgorithmException e) {
+ // This can not happen - HmacSHA256 is supported by the platform.
+ throw new AssertionError(e);
+ }
+ sha256.init(new SecretKeySpec(salt, AES));
+
+ return sha256.doFinal(inputKeyMaterial);
+ }
+
+ /**
+ * Special case of HKDF (RFC 5869) expansion function, using the SHA-256 hash function and
+ * allowing for a maximum output length of 256 bits.
+ *
+ * <p>IMPORTANT: The use or edit of this method requires a security review.
+ *
+ * @param pseudoRandomKey Generated by {@link #hkdfSha256Extract(byte[], byte[])}.
+ * @param info Arbitrary information the derived key should be bound to.
+ * @return Raw derived key bytes = HMAC-SHA256(pseudoRandomKey, info | 0x01).
+ * @throws InvalidKeyException If the salt can not be used as a valid key.
+ */
+ private static byte[] hkdfSha256Expand(byte[] pseudoRandomKey, byte[] info)
+ throws InvalidKeyException {
+ // Note that RFC 5869 computes number of blocks N = ceil(hash length / output length), but
+ // here we only deal with a 256 bit hash up to a 256 bit output, yielding N=1.
+ Mac sha256;
+ try {
+ sha256 = Mac.getInstance(HmacSHA256);
+ } catch (NoSuchAlgorithmException e) {
+ // This can not happen - HmacSHA256 is supported by the platform.
+ throw new AssertionError(e);
+ }
+ sha256.init(new SecretKeySpec(pseudoRandomKey, AES));
+
+ sha256.update(info);
+ sha256.update(CONSTANT_01);
+ return sha256.doFinal();
+ }
+}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpoint.java b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpoint.java
new file mode 100644
index 000000000000..e867e7c1b801
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpoint.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup.encryption.chunking.cdc;
+
+import static com.android.internal.util.Preconditions.checkArgument;
+
+import com.android.server.backup.encryption.chunking.cdc.ContentDefinedChunker.BreakpointPredicate;
+
+/**
+ * Function to determine whether a 64-bit fingerprint ought to be a chunk breakpoint.
+ *
+ * <p>This works by checking whether there are at least n leading zeros in the fingerprint. n is
+ * calculated to on average cause a breakpoint after a given number of trials (provided in the
+ * constructor). This allows us to choose a number of trials that gives a desired average chunk
+ * size. This works because the fingerprint is pseudo-randomly distributed.
+ */
+public class IsChunkBreakpoint implements BreakpointPredicate {
+ private final int mLeadingZeros;
+ private final long mBitmask;
+
+ /**
+ * A new instance that causes a breakpoint after a given number of trials on average.
+ *
+ * @param averageNumberOfTrialsUntilBreakpoint The number of trials after which on average to
+ * create a new chunk. If this is not a power of 2, some precision is sacrificed (i.e., on
+ * average, breaks will actually happen after the nearest power of 2 to the average number
+ * of trials passed in).
+ */
+ public IsChunkBreakpoint(long averageNumberOfTrialsUntilBreakpoint) {
+ checkArgument(
+ averageNumberOfTrialsUntilBreakpoint >= 0,
+ "Average number of trials must be non-negative");
+
+ // Want n leading zeros after t trials.
+ // P(leading zeros = n) = 1/2^n
+ // Expected num trials to get n leading zeros = 1/2^-n
+ // t = 1/2^-n
+ // n = log2(t)
+ mLeadingZeros = (int) Math.round(log2(averageNumberOfTrialsUntilBreakpoint));
+ mBitmask = ~(~0L >>> mLeadingZeros);
+ }
+
+ /**
+ * Returns {@code true} if {@code fingerprint} indicates that there should be a chunk
+ * breakpoint.
+ */
+ @Override
+ public boolean isBreakpoint(long fingerprint) {
+ return (fingerprint & mBitmask) == 0;
+ }
+
+ /** Returns the number of leading zeros in the fingerprint that causes a breakpoint. */
+ public int getLeadingZeros() {
+ return mLeadingZeros;
+ }
+
+ /**
+ * Calculates log base 2 of x. Not the most efficient possible implementation, but it's simple,
+ * obviously correct, and is only invoked on object construction.
+ */
+ private static double log2(double x) {
+ return Math.log(x) / Math.log(2);
+ }
+}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64.java b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64.java
new file mode 100644
index 000000000000..1e14ffa5ad77
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup.encryption.chunking.cdc;
+
+/** Helper to calculate a 64-bit Rabin fingerprint over a 31-byte window. */
+public class RabinFingerprint64 {
+ private static final long DEFAULT_IRREDUCIBLE_POLYNOMIAL_64 = 0x000000000000001BL;
+ private static final int POLYNOMIAL_DEGREE = 64;
+ private static final int SLIDING_WINDOW_SIZE_BYTES = 31;
+
+ private final long mPoly64;
+ // Auxiliary tables to speed up the computation of Rabin fingerprints.
+ private final long[] mTableFP64 = new long[256];
+ private final long[] mTableOutByte = new long[256];
+
+ /**
+ * Constructs a new instance over the given irreducible 64-degree polynomial. It is up to the
+ * caller to determine that the polynomial is irreducible. If it is not the fingerprinting will
+ * not behave as expected.
+ *
+ * @param poly64 The polynomial.
+ */
+ public RabinFingerprint64(long poly64) {
+ mPoly64 = poly64;
+ }
+
+ /** Constructs a new instance using {@code x^64 + x^4 + x + 1} as the irreducible polynomial. */
+ public RabinFingerprint64() {
+ this(DEFAULT_IRREDUCIBLE_POLYNOMIAL_64);
+ computeFingerprintTables64();
+ computeFingerprintTables64Windowed();
+ }
+
+ /**
+ * Computes the fingerprint for the new sliding window given the fingerprint of the previous
+ * sliding window, the byte sliding in, and the byte sliding out.
+ *
+ * @param inChar The new char coming into the sliding window.
+ * @param outChar The left most char sliding out of the window.
+ * @param fingerPrint Fingerprint for previous window.
+ * @return New fingerprint for the new sliding window.
+ */
+ public long computeFingerprint64(byte inChar, byte outChar, long fingerPrint) {
+ return (fingerPrint << 8)
+ ^ (inChar & 0xFF)
+ ^ mTableFP64[(int) (fingerPrint >>> 56)]
+ ^ mTableOutByte[outChar & 0xFF];
+ }
+
+ /** Compute auxiliary tables to speed up the fingerprint computation. */
+ private void computeFingerprintTables64() {
+ long[] degreesRes64 = new long[POLYNOMIAL_DEGREE];
+ degreesRes64[0] = mPoly64;
+ for (int i = 1; i < POLYNOMIAL_DEGREE; i++) {
+ if ((degreesRes64[i - 1] & (1L << 63)) == 0) {
+ degreesRes64[i] = degreesRes64[i - 1] << 1;
+ } else {
+ degreesRes64[i] = (degreesRes64[i - 1] << 1) ^ mPoly64;
+ }
+ }
+ for (int i = 0; i < 256; i++) {
+ int currIndex = i;
+ for (int j = 0; (currIndex > 0) && (j < 8); j++) {
+ if ((currIndex & 0x1) == 1) {
+ mTableFP64[i] ^= degreesRes64[j];
+ }
+ currIndex >>>= 1;
+ }
+ }
+ }
+
+ /**
+ * Compute auxiliary table {@code mTableOutByte} to facilitate the computing of fingerprints for
+ * sliding windows. This table is to take care of the effect on the fingerprint when the
+ * leftmost byte in the window slides out.
+ */
+ private void computeFingerprintTables64Windowed() {
+ // Auxiliary array degsRes64[8] defined by: <code>degsRes64[i] = x^(8 *
+ // SLIDING_WINDOW_SIZE_BYTES + i) mod this.mPoly64.</code>
+ long[] degsRes64 = new long[8];
+ degsRes64[0] = mPoly64;
+ for (int i = 65; i < 8 * (SLIDING_WINDOW_SIZE_BYTES + 1); i++) {
+ if ((degsRes64[(i - 1) % 8] & (1L << 63)) == 0) {
+ degsRes64[i % 8] = degsRes64[(i - 1) % 8] << 1;
+ } else {
+ degsRes64[i % 8] = (degsRes64[(i - 1) % 8] << 1) ^ mPoly64;
+ }
+ }
+ for (int i = 0; i < 256; i++) {
+ int currIndex = i;
+ for (int j = 0; (currIndex > 0) && (j < 8); j++) {
+ if ((currIndex & 0x1) == 1) {
+ mTableOutByte[i] ^= degsRes64[j];
+ }
+ currIndex >>>= 1;
+ }
+ }
+ }
+}
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index e1080260697f..755095ec1b18 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -45,9 +45,9 @@ import com.android.internal.backup.IBackupTransport;
import com.android.internal.util.Preconditions;
import com.android.server.EventLogTags;
import com.android.server.backup.BackupAgentTimeoutParameters;
+import com.android.server.backup.BackupManagerService;
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.FullBackupJob;
-import com.android.server.backup.BackupManagerService;
import com.android.server.backup.TransportManager;
import com.android.server.backup.internal.OnTaskFinishedListener;
import com.android.server.backup.internal.Operation;
@@ -599,7 +599,6 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
cleanUpPipes(enginePipes);
if (currentPackage.applicationInfo != null) {
Slog.i(TAG, "Unbinding agent in " + packageName);
- backupManagerService.addBackupTrace("unbinding " + packageName);
try {
backupManagerService.getActivityManager().unbindBackupAgent(
currentPackage.applicationInfo);
@@ -709,7 +708,6 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
try {
backupManagerService.prepareOperationTimeout(
mCurrentOpToken, fullBackupAgentTimeoutMillis, this, OP_TYPE_BACKUP_WAIT);
- backupManagerService.addBackupTrace("preflighting");
if (MORE_DEBUG) {
Slog.d(TAG, "Preflighting full payload of " + pkg.packageName);
}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 888ad1da3fcc..617430090998 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -3,6 +3,7 @@ java_library_static {
aidl: {
include_dirs: [
+ "frameworks/base/cmds/idmap2/idmap2d/aidl",
"frameworks/native/aidl/binder",
"frameworks/native/cmds/dumpstate/binder",
"system/core/storaged/binder",
@@ -13,6 +14,7 @@ java_library_static {
srcs: [
"java/**/*.java",
":dumpstate_aidl",
+ ":idmap2_aidl",
":netd_aidl",
":netd_metrics_aidl",
":installd_aidl",
diff --git a/services/core/java/com/android/server/AbstractMasterSystemService.java b/services/core/java/com/android/server/AbstractMasterSystemService.java
index c955daf2fae4..6cae887d3ffc 100644
--- a/services/core/java/com/android/server/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/AbstractMasterSystemService.java
@@ -244,7 +244,7 @@ public abstract class AbstractMasterSystemService<S extends AbstractPerUserSyste
*/
@GuardedBy("mLock")
@Nullable
- protected S peekServiceForUserLocked(int userId) {
+ protected S peekServiceForUserLocked(@UserIdInt int userId) {
final int resolvedUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), userId, false, false, null, null);
return mServicesCache.get(resolvedUserId);
@@ -254,7 +254,7 @@ public abstract class AbstractMasterSystemService<S extends AbstractPerUserSyste
* Updates a cached service for a given user.
*/
@GuardedBy("mLock")
- protected void updateCachedServiceLocked(int userId) {
+ protected void updateCachedServiceLocked(@UserIdInt int userId) {
updateCachedServiceLocked(userId, isDisabledLocked(userId));
}
@@ -262,7 +262,7 @@ public abstract class AbstractMasterSystemService<S extends AbstractPerUserSyste
* Checks whether the service is disabled (through {@link UserManager} restrictions) for the
* given user.
*/
- protected boolean isDisabledLocked(int userId) {
+ protected boolean isDisabledLocked(@UserIdInt int userId) {
return mDisabledUsers == null ? false : mDisabledUsers.get(userId);
}
@@ -274,7 +274,7 @@ public abstract class AbstractMasterSystemService<S extends AbstractPerUserSyste
* @return service for the user.
*/
@GuardedBy("mLock")
- protected S updateCachedServiceLocked(int userId, boolean disabled) {
+ protected S updateCachedServiceLocked(@UserIdInt int userId, boolean disabled) {
final S service = getServiceForUserLocked(userId);
if (service != null) {
service.updateLocked(disabled);
@@ -304,7 +304,7 @@ public abstract class AbstractMasterSystemService<S extends AbstractPerUserSyste
* <p>By default doesn't do anything, but can be overridden by subclasses.
*/
@SuppressWarnings("unused")
- protected void onServiceEnabledLocked(S service, @UserIdInt int userId) {
+ protected void onServiceEnabledLocked(@NonNull S service, @UserIdInt int userId) {
}
/**
@@ -314,15 +314,23 @@ public abstract class AbstractMasterSystemService<S extends AbstractPerUserSyste
*/
@GuardedBy("mLock")
@NonNull
- protected S removeCachedServiceLocked(@UserIdInt int userId) {
+ private S removeCachedServiceLocked(@UserIdInt int userId) {
final S service = peekServiceForUserLocked(userId);
if (service != null) {
mServicesCache.delete(userId);
+ onServiceRemoved(service, userId);
}
return service;
}
/**
+ * Called after the service is removed from the cache.
+ */
+ @SuppressWarnings("unused")
+ protected void onServiceRemoved(@NonNull S service, @UserIdInt int userId) {
+ }
+
+ /**
* Visits all services in the cache.
*/
@GuardedBy("mLock")
diff --git a/services/core/java/com/android/server/AbstractPerUserSystemService.java b/services/core/java/com/android/server/AbstractPerUserSystemService.java
index 201abe689283..97977df2e8a6 100644
--- a/services/core/java/com/android/server/AbstractPerUserSystemService.java
+++ b/services/core/java/com/android/server/AbstractPerUserSystemService.java
@@ -167,7 +167,7 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
@GuardedBy("mLock")
protected final int getServiceUidLocked() {
if (mServiceInfo == null) {
- Slog.w(mTag, "getServiceUidLocked(): no mServiceInfo");
+ if (mMaster.verbose) Slog.v(mTag, "getServiceUidLocked(): no mServiceInfo");
return Process.INVALID_UID;
}
return mServiceInfo.applicationInfo.uid;
@@ -267,8 +267,18 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
@GuardedBy("mLock")
protected void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
pw.print(prefix); pw.print("User: "); pw.println(mUserId);
- pw.print(prefix); pw.print("Disabled: "); pw.println(mDisabled);
+ pw.print(prefix); pw.print("Disabled by UserManager: "); pw.println(mDisabled);
pw.print(prefix); pw.print("Setup complete: "); pw.println(mSetupComplete);
- pw.print(prefix); pw.print("Service name: "); pw.println(getComponentNameFromSettings());
+ if (mServiceInfo != null) {
+ pw.print(prefix); pw.print("Service UID: ");
+ pw.println(mServiceInfo.applicationInfo.uid);
+ }
+ final String componentName = getComponentNameFromSettings();
+ if (componentName != null) {
+ pw.print(prefix); pw.print("Service name: ");
+ pw.println(componentName);
+ } else {
+ pw.println("No service package set");
+ }
}
}
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 5814064e5fbd..fa98da541e57 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -80,6 +80,7 @@ import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.util.Xml;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsActiveCallback;
import com.android.internal.app.IAppOpsCallback;
@@ -219,6 +220,7 @@ public class AppOpsService extends IAppOpsService.Stub {
SparseIntArray mProfileOwners;
+ @GuardedBy("this")
private CheckOpsDelegate mCheckOpsDelegate;
/**
@@ -1589,24 +1591,28 @@ public class AppOpsService extends IAppOpsService.Stub {
public int checkOperation(int code, int uid, String packageName) {
final CheckOpsDelegate delegate;
synchronized (this) {
- if (mCheckOpsDelegate == null) {
- return checkOperationImpl(code, uid, packageName);
- }
delegate = mCheckOpsDelegate;
}
+ if (delegate == null) {
+ return checkOperationImpl(code, uid, packageName);
+ }
return delegate.checkOperation(code, uid, packageName,
AppOpsService.this::checkOperationImpl);
}
private int checkOperationImpl(int code, int uid, String packageName) {
+ verifyIncomingUid(uid);
+ verifyIncomingOp(code);
+ String resolvedPackageName = resolvePackageName(uid, packageName);
+ if (resolvedPackageName == null) {
+ return AppOpsManager.MODE_IGNORED;
+ }
+ return checkOperationUnchecked(code, uid, resolvedPackageName);
+ }
+
+ private int checkOperationUnchecked(int code, int uid, String packageName) {
synchronized (this) {
- verifyIncomingUid(uid);
- verifyIncomingOp(code);
- String resolvedPackageName = resolvePackageName(uid, packageName);
- if (resolvedPackageName == null) {
- return AppOpsManager.MODE_IGNORED;
- }
- if (isOpRestrictedLocked(uid, code, resolvedPackageName)) {
+ if (isOpRestrictedLocked(uid, code, packageName)) {
return AppOpsManager.MODE_IGNORED;
}
code = AppOpsManager.opToSwitch(code);
@@ -1615,7 +1621,7 @@ public class AppOpsService extends IAppOpsService.Stub {
&& uidState.opModes.indexOfKey(code) >= 0) {
return uidState.opModes.get(code);
}
- Op op = getOpLocked(code, uid, resolvedPackageName, false, true, false);
+ Op op = getOpLocked(code, uid, packageName, false, true, false);
if (op == null) {
return AppOpsManager.opToDefaultMode(code);
}
@@ -1627,31 +1633,31 @@ public class AppOpsService extends IAppOpsService.Stub {
public int checkAudioOperation(int code, int usage, int uid, String packageName) {
final CheckOpsDelegate delegate;
synchronized (this) {
- if (mCheckOpsDelegate == null) {
- return checkAudioOperationImpl(code, usage, uid, packageName);
- }
delegate = mCheckOpsDelegate;
}
+ if (delegate == null) {
+ return checkAudioOperationImpl(code, usage, uid, packageName);
+ }
return delegate.checkAudioOperation(code, usage, uid, packageName,
AppOpsService.this::checkAudioOperationImpl);
}
private int checkAudioOperationImpl(int code, int usage, int uid, String packageName) {
- synchronized (this) {
- boolean suspended;
- try {
- suspended = isPackageSuspendedForUser(packageName, uid);
- } catch (IllegalArgumentException ex) {
- // Package not found.
- suspended = false;
- }
+ boolean suspended;
+ try {
+ suspended = isPackageSuspendedForUser(packageName, uid);
+ } catch (IllegalArgumentException ex) {
+ // Package not found.
+ suspended = false;
+ }
- if (suspended) {
- Slog.i(TAG, "Audio disabled for suspended package=" + packageName
- + " for uid=" + uid);
- return AppOpsManager.MODE_IGNORED;
- }
+ if (suspended) {
+ Slog.i(TAG, "Audio disabled for suspended package=" + packageName
+ + " for uid=" + uid);
+ return AppOpsManager.MODE_IGNORED;
+ }
+ synchronized (this) {
final int mode = checkRestrictionLocked(code, usage, uid, packageName);
if (mode != AppOpsManager.MODE_ALLOWED) {
return mode;
@@ -1754,11 +1760,11 @@ public class AppOpsService extends IAppOpsService.Stub {
public int noteOperation(int code, int uid, String packageName) {
final CheckOpsDelegate delegate;
synchronized (this) {
- if (mCheckOpsDelegate == null) {
- return noteOperationImpl(code, uid, packageName);
- }
delegate = mCheckOpsDelegate;
}
+ if (delegate == null) {
+ return noteOperationImpl(code, uid, packageName);
+ }
return delegate.noteOperation(code, uid, packageName,
AppOpsService.this::noteOperationImpl);
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 78e82b6f7821..923ac0063baf 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -186,8 +186,6 @@ class StorageManagerService extends IStorageManager.Stub
private static final boolean ENABLE_ISOLATED_STORAGE = SystemProperties
.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false);
- private static final String SHARED_SANDBOX_ID_PREFIX = "shared:";
-
public static class Lifecycle extends SystemService {
private StorageManagerService mStorageManagerService;
@@ -1501,7 +1499,8 @@ class StorageManagerService extends IStorageManager.Stub
}
private static String getSandboxId(String packageName, String sharedUserId) {
- return sharedUserId == null ? packageName : SHARED_SANDBOX_ID_PREFIX + sharedUserId;
+ return sharedUserId == null
+ ? packageName : StorageManager.SHARED_SANDBOX_PREFIX + sharedUserId;
}
private void connect() {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index a33ac700ba95..c660cc6c6f75 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -192,10 +192,10 @@ public final class ActiveServices {
public void stopForegroundServicesForUidPackage(final int uid, final String packageName) {
synchronized (mAm) {
final ServiceMap smap = getServiceMapLocked(UserHandle.getUserId(uid));
- final int N = smap.mServicesByName.size();
+ final int N = smap.mServicesByInstanceName.size();
final ArrayList<ServiceRecord> toStop = new ArrayList<>(N);
for (int i = 0; i < N; i++) {
- final ServiceRecord r = smap.mServicesByName.valueAt(i);
+ final ServiceRecord r = smap.mServicesByInstanceName.valueAt(i);
if (uid == r.serviceInfo.applicationInfo.uid
|| packageName.equals(r.serviceInfo.packageName)) {
if (r.isForeground) {
@@ -246,7 +246,7 @@ public final class ActiveServices {
*/
final class ServiceMap extends Handler {
final int mUserId;
- final ArrayMap<ComponentName, ServiceRecord> mServicesByName = new ArrayMap<>();
+ final ArrayMap<ComponentName, ServiceRecord> mServicesByInstanceName = new ArrayMap<>();
final ArrayMap<Intent.FilterComparison, ServiceRecord> mServicesByIntent = new ArrayMap<>();
final ArrayList<ServiceRecord> mDelayedStartList = new ArrayList<>();
@@ -368,7 +368,7 @@ public final class ActiveServices {
// TODO: Deal with global services
if (DEBUG_MU)
Slog.v(TAG_MU, "getServiceByNameLocked(" + name + "), callingUser = " + callingUser);
- return getServiceMapLocked(callingUser).mServicesByName.get(name);
+ return getServiceMapLocked(callingUser).mServicesByInstanceName.get(name);
}
boolean hasBackgroundServicesLocked(int callingUser) {
@@ -386,7 +386,7 @@ public final class ActiveServices {
}
ArrayMap<ComponentName, ServiceRecord> getServicesLocked(int callingUser) {
- return getServiceMapLocked(callingUser).mServicesByName;
+ return getServiceMapLocked(callingUser).mServicesByInstanceName;
}
private boolean appRestrictedAnyInBackground(final int uid, final String packageName) {
@@ -416,7 +416,7 @@ public final class ActiveServices {
}
ServiceLookupResult res =
- retrieveServiceLocked(service, resolvedType, callingPackage,
+ retrieveServiceLocked(service, null, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false, false);
if (res == null) {
return null;
@@ -444,7 +444,7 @@ public final class ActiveServices {
boolean forcedStandby = false;
if (bgLaunch && appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
if (DEBUG_FOREGROUND_SERVICE) {
- Slog.d(TAG, "Forcing bg-only service start only for " + r.shortName
+ Slog.d(TAG, "Forcing bg-only service start only for " + r.shortInstanceName
+ " : bgLaunch=" + bgLaunch + " callerFg=" + callerFg);
}
forcedStandby = true;
@@ -464,7 +464,7 @@ public final class ActiveServices {
// Not allowed, fall back to normal start service, failing siliently
// if background check restricts that.
Slog.w(TAG, "startForegroundService not allowed due to app op: service "
- + service + " to " + r.name.flattenToShortString()
+ + service + " to " + r.shortInstanceName
+ " from pid=" + callingPid + " uid=" + callingUid
+ " pkg=" + callingPackage);
fgRequired = false;
@@ -484,7 +484,7 @@ public final class ActiveServices {
r.appInfo.targetSdkVersion, callingPid, false, false, forcedStandby);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
Slog.w(TAG, "Background start not allowed: service "
- + service + " to " + r.name.flattenToShortString()
+ + service + " to " + r.shortInstanceName
+ " from pid=" + callingPid + " uid=" + callingUid
+ " pkg=" + callingPackage + " startFg?=" + fgRequired);
if (allowed == ActivityManager.APP_START_MODE_DELAYED || forceSilentAbort) {
@@ -677,6 +677,8 @@ public final class ActiveServices {
stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
}
r.callStart = false;
+ StatsLog.write(StatsLog.SERVICE_STATE_CHANGED, r.appInfo.uid, r.name.getPackageName(),
+ r.name.getClassName(), StatsLog.SERVICE_STATE_CHANGED__STATE__START);
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
}
@@ -715,6 +717,9 @@ public final class ActiveServices {
service.delayedStop = true;
return;
}
+ StatsLog.write(StatsLog.SERVICE_STATE_CHANGED, service.appInfo.uid,
+ service.name.getPackageName(), service.name.getClassName(),
+ StatsLog.SERVICE_STATE_CHANGED__STATE__STOP);
synchronized (service.stats.getBatteryStats()) {
service.stats.stopRunningLocked();
}
@@ -741,7 +746,7 @@ public final class ActiveServices {
}
// If this service is active, make sure it is stopped.
- ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, null,
+ ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, null,
Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false, false, false);
if (r != null) {
if (r.record != null) {
@@ -765,8 +770,8 @@ public final class ActiveServices {
ServiceMap services = mServiceMap.get(UserHandle.getUserId(uid));
ArrayList<ServiceRecord> stopping = null;
if (services != null) {
- for (int i=services.mServicesByName.size()-1; i>=0; i--) {
- ServiceRecord service = services.mServicesByName.valueAt(i);
+ for (int i = services.mServicesByInstanceName.size() - 1; i >= 0; i--) {
+ ServiceRecord service = services.mServicesByInstanceName.valueAt(i);
if (service.appInfo.uid == uid && service.startRequested) {
if (mAm.getAppStartModeLocked(service.appInfo.uid, service.packageName,
service.appInfo.targetSdkVersion, -1, false, false, false)
@@ -774,7 +779,7 @@ public final class ActiveServices {
if (stopping == null) {
stopping = new ArrayList<>();
}
- String compName = service.name.flattenToShortString();
+ String compName = service.shortInstanceName;
EventLogTags.writeAmStopIdleService(service.appInfo.uid, compName);
StringBuilder sb = new StringBuilder(64);
sb.append("Stopping service due to app idle: ");
@@ -801,7 +806,7 @@ public final class ActiveServices {
}
IBinder peekServiceLocked(Intent service, String resolvedType, String callingPackage) {
- ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, callingPackage,
+ ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, callingPackage,
Binder.getCallingPid(), Binder.getCallingUid(),
UserHandle.getCallingUserId(), false, false, false, false);
@@ -856,6 +861,8 @@ public final class ActiveServices {
}
}
+ StatsLog.write(StatsLog.SERVICE_STATE_CHANGED, r.appInfo.uid, r.name.getPackageName(),
+ r.name.getClassName(), StatsLog.SERVICE_STATE_CHANGED__STATE__STOP);
synchronized (r.stats.getBatteryStats()) {
r.stats.stopRunningLocked();
}
@@ -1228,7 +1235,7 @@ public final class ActiveServices {
case AppOpsManager.MODE_IGNORED:
// Whoops, silently ignore this.
Slog.w(TAG, "Service.startForeground() not allowed due to app op: service "
- + r.shortName);
+ + r.shortInstanceName);
ignoreForeground = true;
break;
default:
@@ -1239,7 +1246,7 @@ public final class ActiveServices {
appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) {
Slog.w(TAG,
"Service.startForeground() not allowed due to bg restriction: service "
- + r.shortName);
+ + r.shortInstanceName);
// Back off of any foreground expectations around this service, since we've
// just turned down its fg request.
updateServiceForegroundLocked(r.app, false);
@@ -1293,7 +1300,7 @@ public final class ActiveServices {
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName,
true);
StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
- r.appInfo.uid, r.shortName,
+ r.appInfo.uid, r.shortInstanceName,
StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__ENTER);
mAm.updateForegroundServiceUsageStats(r.name, r.userId, true);
}
@@ -1343,7 +1350,7 @@ public final class ActiveServices {
AppOpsManager.getToken(mAm.mAppOpsService),
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
- r.appInfo.uid, r.shortName,
+ r.appInfo.uid, r.shortInstanceName,
StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
if (r.app != null) {
@@ -1373,8 +1380,8 @@ public final class ActiveServices {
// due the other service.
ServiceMap sm = getServiceMapLocked(r.userId);
if (sm != null) {
- for (int i = sm.mServicesByName.size()-1; i >= 0; i--) {
- ServiceRecord other = sm.mServicesByName.valueAt(i);
+ for (int i = sm.mServicesByInstanceName.size() - 1; i >= 0; i--) {
+ ServiceRecord other = sm.mServicesByInstanceName.valueAt(i);
if (other != r && other.foregroundId == r.foregroundId
&& other.packageName.equals(r.packageName)) {
// Found one! Abort the cancel.
@@ -1466,7 +1473,8 @@ public final class ActiveServices {
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
- String callingPackage, final int userId) throws TransactionTooLargeException {
+ String instanceName, String callingPackage, final int userId)
+ throws TransactionTooLargeException {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
+ " type=" + resolvedType + " conn=" + connection.asBinder()
+ " flags=0x" + Integer.toHexString(flags));
@@ -1530,8 +1538,9 @@ public final class ActiveServices {
final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0;
ServiceLookupResult res =
- retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
- Binder.getCallingUid(), userId, true, callerFg, isBindExternal, allowInstant);
+ retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
+ Binder.getCallingPid(), Binder.getCallingUid(), userId, true,
+ callerFg, isBindExternal, allowInstant);
if (res == null) {
return 0;
}
@@ -1637,7 +1646,7 @@ public final class ActiveServices {
mAm.startAssociationLocked(callerApp.uid, callerApp.processName,
callerApp.getCurProcState(), s.appInfo.uid, s.appInfo.longVersionCode,
- s.name, s.processName);
+ s.instanceName, s.processName);
// Once the apps have become associated, if one of them is caller is ephemeral
// the target app should now be able to see the calling app
mAm.grantEphemeralAccessLocked(callerApp.userId, service,
@@ -1709,7 +1718,7 @@ public final class ActiveServices {
try {
c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
- Slog.w(TAG, "Failure sending service " + s.shortName
+ Slog.w(TAG, "Failure sending service " + s.shortInstanceName
+ " to connection " + c.conn.asBinder()
+ " (in " + c.binding.client.processName + ")", e);
}
@@ -1763,9 +1772,9 @@ public final class ActiveServices {
try {
c.conn.connected(r.name, service, false);
} catch (Exception e) {
- Slog.w(TAG, "Failure sending service " + r.name +
- " to connection " + c.conn.asBinder() +
- " (in " + c.binding.client.processName + ")", e);
+ Slog.w(TAG, "Failure sending service " + r.shortInstanceName
+ + " to connection " + c.conn.asBinder()
+ + " (in " + c.binding.client.processName + ")", e);
}
}
}
@@ -1898,7 +1907,8 @@ public final class ActiveServices {
}
private ServiceLookupResult retrieveServiceLocked(Intent service,
- String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
+ String instanceName, String resolvedType, String callingPackage,
+ int callingPid, int callingUid, int userId,
boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal,
boolean allowInstant) {
ServiceRecord r = null;
@@ -1909,12 +1919,23 @@ public final class ActiveServices {
ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE, "service", null);
ServiceMap smap = getServiceMapLocked(userId);
- final ComponentName comp = service.getComponent();
+ final ComponentName comp;
+ if (instanceName == null) {
+ comp = service.getComponent();
+ } else {
+ final ComponentName realComp = service.getComponent();
+ if (realComp == null) {
+ throw new IllegalArgumentException("Can't use custom instance name '" + instanceName
+ + "' without expicit component in Intent");
+ }
+ comp = new ComponentName(realComp.getPackageName(),
+ realComp.getClassName() + ":" + instanceName);
+ }
if (comp != null) {
- r = smap.mServicesByName.get(comp);
+ r = smap.mServicesByInstanceName.get(comp);
if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE, "Retrieved by component: " + r);
}
- if (r == null && !isBindExternal) {
+ if (r == null && !isBindExternal && instanceName == null) {
Intent.FilterComparison filter = new Intent.FilterComparison(service);
r = smap.mServicesByIntent.get(filter);
if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE, "Retrieved by intent: " + r);
@@ -1936,24 +1957,29 @@ public final class ActiveServices {
// TODO: come back and remove this assumption to triage all services
ResolveInfo rInfo = mAm.getPackageManagerInternalLocked().resolveService(service,
resolvedType, flags, userId, callingUid);
- ServiceInfo sInfo =
- rInfo != null ? rInfo.serviceInfo : null;
+ ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null;
if (sInfo == null) {
Slog.w(TAG_SERVICE, "Unable to start service " + service + " U=" + userId +
": not found");
return null;
}
- ComponentName name = new ComponentName(
+ if (instanceName != null
+ && (sInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) == 0) {
+ throw new IllegalArgumentException("Can't use instance name '" + instanceName
+ + "' with non-isolated service '" + sInfo.name + "'");
+ }
+ ComponentName className = new ComponentName(
sInfo.applicationInfo.packageName, sInfo.name);
+ ComponentName name = comp != null ? comp : className;
if ((sInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) != 0) {
if (isBindExternal) {
if (!sInfo.exported) {
- throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name +
- " is not exported");
+ throw new SecurityException("BIND_EXTERNAL_SERVICE failed, "
+ + className + " is not exported");
}
if ((sInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) == 0) {
- throw new SecurityException("BIND_EXTERNAL_SERVICE failed, " + name +
- " is not an isolatedProcess");
+ throw new SecurityException("BIND_EXTERNAL_SERVICE failed, "
+ + className + " is not an isolatedProcess");
}
// Run the service under the calling package's application.
ApplicationInfo aInfo = AppGlobals.getPackageManager().getApplicationInfo(
@@ -1967,6 +1993,9 @@ public final class ActiveServices {
sInfo.applicationInfo.packageName = aInfo.packageName;
sInfo.applicationInfo.uid = aInfo.uid;
name = new ComponentName(aInfo.packageName, name.getClassName());
+ className = new ComponentName(aInfo.packageName,
+ instanceName == null ? className.getClassName()
+ : (className.getClassName() + ":" + instanceName));
service.setComponent(name);
} else {
throw new SecurityException("BIND_EXTERNAL_SERVICE required for " +
@@ -1986,7 +2015,7 @@ public final class ActiveServices {
sInfo = new ServiceInfo(sInfo);
sInfo.applicationInfo = mAm.getAppInfoForUser(sInfo.applicationInfo, userId);
}
- r = smap.mServicesByName.get(name);
+ r = smap.mServicesByInstanceName.get(name);
if (DEBUG_SERVICE && r != null) Slog.v(TAG_SERVICE,
"Retrieved via pm by intent: " + r);
if (r == null && createIfNeeded) {
@@ -1997,19 +2026,20 @@ public final class ActiveServices {
final BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
ss = stats.getServiceStatsLocked(
- sInfo.applicationInfo.uid, sInfo.packageName,
- sInfo.name);
+ sInfo.applicationInfo.uid, name.getPackageName(),
+ name.getClassName());
}
- r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
+ r = new ServiceRecord(mAm, ss, className, name, filter, sInfo, callingFromFg,
+ res);
res.setService(r);
- smap.mServicesByName.put(name, r);
+ smap.mServicesByInstanceName.put(name, r);
smap.mServicesByIntent.put(filter, r);
// Make sure this component isn't in the pending list.
for (int i=mPendingServices.size()-1; i>=0; i--) {
final ServiceRecord pr = mPendingServices.get(i);
if (pr.serviceInfo.applicationInfo.uid == sInfo.applicationInfo.uid
- && pr.name.equals(name)) {
+ && pr.instanceName.equals(name)) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Remove pending: " + pr);
mPendingServices.remove(i);
}
@@ -2024,14 +2054,14 @@ public final class ActiveServices {
if (mAm.checkComponentPermission(r.permission,
callingPid, callingUid, r.appInfo.uid, r.exported) != PERMISSION_GRANTED) {
if (!r.exported) {
- Slog.w(TAG, "Permission Denial: Accessing service " + r.name
+ Slog.w(TAG, "Permission Denial: Accessing service " + r.shortInstanceName
+ " from pid=" + callingPid
+ ", uid=" + callingUid
+ " that is not exported from uid " + r.appInfo.uid);
return new ServiceLookupResult(null, "not exported from uid "
+ r.appInfo.uid);
}
- Slog.w(TAG, "Permission Denial: Accessing service " + r.name
+ Slog.w(TAG, "Permission Denial: Accessing service " + r.shortInstanceName
+ " from pid=" + callingPid
+ ", uid=" + callingUid
+ " requires " + r.permission);
@@ -2040,7 +2070,7 @@ public final class ActiveServices {
final int opCode = AppOpsManager.permissionToOpCode(r.permission);
if (opCode != AppOpsManager.OP_NONE && mAm.mAppOpsService.noteOperation(
opCode, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
- Slog.w(TAG, "Appop Denial: Accessing service " + r.name
+ Slog.w(TAG, "Appop Denial: Accessing service " + r.shortInstanceName
+ " from pid=" + callingPid
+ ", uid=" + callingUid
+ " requires appop " + AppOpsManager.opToName(opCode));
@@ -2061,7 +2091,7 @@ public final class ActiveServices {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, ">>> EXECUTING "
+ why + " of " + r + " in app " + r.app);
else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, ">>> EXECUTING "
- + why + " of " + r.shortName);
+ + why + " of " + r.shortInstanceName);
// For b/34123235: Services within the system server won't start until SystemServer
// does Looper.loop(), so we shouldn't try to start/bind to them too early in the boot
@@ -2146,14 +2176,14 @@ public final class ActiveServices {
boolean canceled = false;
if (mAm.mAtmInternal.isShuttingDown()) {
- Slog.w(TAG, "Not scheduling restart of crashed service " + r.shortName
+ Slog.w(TAG, "Not scheduling restart of crashed service " + r.shortInstanceName
+ " - system is shutting down");
return false;
}
ServiceMap smap = getServiceMapLocked(r.userId);
- if (smap.mServicesByName.get(r.name) != r) {
- ServiceRecord cur = smap.mServicesByName.get(r.name);
+ if (smap.mServicesByInstanceName.get(r.instanceName) != r) {
+ ServiceRecord cur = smap.mServicesByInstanceName.get(r.instanceName);
Slog.wtf(TAG, "Attempting to schedule restart of " + r
+ " when found in map: " + cur);
return false;
@@ -2184,7 +2214,7 @@ public final class ActiveServices {
if (resetTime < dur) resetTime = dur;
} else {
Slog.w(TAG, "Canceling start item " + si.intent + " in service "
- + r.name);
+ + r.shortInstanceName);
canceled = true;
}
}
@@ -2256,9 +2286,9 @@ public final class ActiveServices {
mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime);
r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Slog.w(TAG, "Scheduling restart of crashed service "
- + r.shortName + " in " + r.restartDelay + "ms");
+ + r.shortInstanceName + " in " + r.restartDelay + "ms");
EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
- r.userId, r.shortName, r.restartDelay);
+ r.userId, r.shortInstanceName, r.restartDelay);
return canceled;
}
@@ -2393,7 +2423,7 @@ public final class ActiveServices {
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
- Slog.w(TAG, "Exception when starting service " + r.shortName, e);
+ Slog.w(TAG, "Exception when starting service " + r.shortInstanceName, e);
}
// If a dead object exception was thrown -- fall through to
@@ -2417,7 +2447,7 @@ public final class ActiveServices {
// to be executed when the app comes up.
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
- hostingType, r.name, false, isolated, false)) == null) {
+ hostingType, r.instanceName, false, isolated, false)) == null) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
@@ -2488,11 +2518,14 @@ public final class ActiveServices {
try {
if (LOG_SERVICE_START_STOP) {
String nameTerm;
- int lastPeriod = r.shortName.lastIndexOf('.');
- nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
+ int lastPeriod = r.shortInstanceName.lastIndexOf('.');
+ nameTerm = lastPeriod >= 0 ? r.shortInstanceName.substring(lastPeriod)
+ : r.shortInstanceName;
EventLogTags.writeAmCreateService(
r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
}
+ StatsLog.write(StatsLog.SERVICE_LAUNCH_REPORTED, r.appInfo.uid, r.name.getPackageName(),
+ r.name.getClassName());
synchronized (r.stats.getBatteryStats()) {
r.stats.startLaunchedLocked();
}
@@ -2705,9 +2738,9 @@ public final class ActiveServices {
try {
cr.conn.connected(r.name, null, true);
} catch (Exception e) {
- Slog.w(TAG, "Failure disconnecting service " + r.name +
- " to connection " + c.get(i).conn.asBinder() +
- " (in " + c.get(i).binding.client.processName + ")", e);
+ Slog.w(TAG, "Failure disconnecting service " + r.shortInstanceName
+ + " to connection " + c.get(i).conn.asBinder()
+ + " (in " + c.get(i).binding.client.processName + ")", e);
}
}
}
@@ -2728,7 +2761,7 @@ public final class ActiveServices {
ibr.intent.getIntent());
} catch (Exception e) {
Slog.w(TAG, "Exception when unbinding service "
- + r.shortName, e);
+ + r.shortInstanceName, e);
serviceProcessGoneLocked(r);
}
}
@@ -2773,14 +2806,14 @@ public final class ActiveServices {
}
final ServiceMap smap = getServiceMapLocked(r.userId);
- ServiceRecord found = smap.mServicesByName.remove(r.name);
+ ServiceRecord found = smap.mServicesByInstanceName.remove(r.instanceName);
// Note when this method is called by bringUpServiceLocked(), the service is not found
- // in mServicesByName and found will be null.
+ // in mServicesByInstanceName and found will be null.
if (found != null && found != r) {
// This is not actually the service we think is running... this should not happen,
// but if it does, fail hard.
- smap.mServicesByName.put(r.name, found);
+ smap.mServicesByInstanceName.put(r.instanceName, found);
throw new IllegalStateException("Bringing down " + r + " but actually running "
+ found);
}
@@ -2807,8 +2840,8 @@ public final class ActiveServices {
mAm.mAppOpsService.finishOperation(
AppOpsManager.getToken(mAm.mAppOpsService),
AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName);
- StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid, r.shortName,
- StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
+ StatsLog.write(StatsLog.FOREGROUND_SERVICE_STATE_CHANGED, r.appInfo.uid,
+ r.shortInstanceName, StatsLog.FOREGROUND_SERVICE_STATE_CHANGED__STATE__EXIT);
mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
}
@@ -2838,7 +2871,7 @@ public final class ActiveServices {
r.app.thread.scheduleStopService(r);
} catch (Exception e) {
Slog.w(TAG, "Exception when destroying service "
- + r.shortName, e);
+ + r.shortInstanceName, e);
serviceProcessGoneLocked(r);
}
} else {
@@ -2915,7 +2948,7 @@ public final class ActiveServices {
}
mAm.stopAssociationLocked(b.client.uid, b.client.processName, s.appInfo.uid,
- s.appInfo.longVersionCode, s.name, s.processName);
+ s.appInfo.longVersionCode, s.instanceName, s.processName);
if (b.connections.size() == 0) {
b.intent.apps.remove(b.client);
@@ -2942,7 +2975,7 @@ public final class ActiveServices {
b.intent.doRebind = false;
s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
} catch (Exception e) {
- Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
+ Slog.w(TAG, "Exception when unbinding service " + s.shortInstanceName, e);
serviceProcessGoneLocked(s);
}
}
@@ -3061,17 +3094,17 @@ public final class ActiveServices {
+ ": nesting=" + r.executeNesting
+ ", inDestroying=" + inDestroying + ", app=" + r.app);
else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
- "<<< DONE EXECUTING " + r.shortName);
+ "<<< DONE EXECUTING " + r.shortInstanceName);
r.executeNesting--;
if (r.executeNesting <= 0) {
if (r.app != null) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
- "Nesting at 0 of " + r.shortName);
+ "Nesting at 0 of " + r.shortInstanceName);
r.app.execServicesFg = false;
r.app.executingServices.remove(r);
if (r.app.executingServices.size() == 0) {
if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
- "No more executingServices of " + r.shortName);
+ "No more executingServices of " + r.shortInstanceName);
mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
} else if (r.executeFg) {
// Need to re-evaluate whether the app still needs to be in the foreground.
@@ -3141,7 +3174,7 @@ public final class ActiveServices {
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting service "
- + sr.shortName, e);
+ + sr.shortInstanceName, e);
throw e;
}
}
@@ -3227,7 +3260,8 @@ public final class ActiveServices {
if (userId == UserHandle.USER_ALL) {
for (int i = mServiceMap.size() - 1; i >= 0; i--) {
didSomething |= collectPackageServicesLocked(packageName, filterByClasses,
- evenPersistent, doit, killProcess, mServiceMap.valueAt(i).mServicesByName);
+ evenPersistent, doit, killProcess,
+ mServiceMap.valueAt(i).mServicesByInstanceName);
if (!doit && didSomething) {
return true;
}
@@ -3238,7 +3272,7 @@ public final class ActiveServices {
} else {
ServiceMap smap = mServiceMap.get(userId);
if (smap != null) {
- ArrayMap<ComponentName, ServiceRecord> items = smap.mServicesByName;
+ ArrayMap<ComponentName, ServiceRecord> items = smap.mServicesByInstanceName;
didSomething = collectPackageServicesLocked(packageName, filterByClasses,
evenPersistent, doit, killProcess, items);
}
@@ -3288,7 +3322,7 @@ public final class ActiveServices {
ServiceRecord sr = services.get(i);
if (sr.startRequested) {
if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {
- Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task");
+ Slog.i(TAG, "Stopping service " + sr.shortInstanceName + ": remove task");
stopServiceLocked(sr);
} else {
sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,
@@ -3326,7 +3360,7 @@ public final class ActiveServices {
} catch (Exception e) {
// todo: this should be asynchronous!
Slog.w(TAG, "Exception thrown disconnected servce "
- + r.shortName
+ + r.shortInstanceName
+ " from app " + app.processName, e);
}
}
@@ -3400,7 +3434,7 @@ public final class ActiveServices {
if (false && proc != null && !proc.isPersistent() && proc.thread != null
&& proc.pid != 0 && proc.pid != ActivityManagerService.MY_PID
&& proc.setProcState >= ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
- proc.kill("bound to service " + sr.name.flattenToShortString()
+ proc.kill("bound to service " + sr.shortInstanceName
+ " in dying proc " + (app != null ? app.processName : "??"), true);
}
}
@@ -3421,7 +3455,7 @@ public final class ActiveServices {
// Sanity check: if the service listed for the app is not one
// we actually are maintaining, just let it drop.
- final ServiceRecord curRec = smap.mServicesByName.get(sr.name);
+ final ServiceRecord curRec = smap.mServicesByInstanceName.get(sr.instanceName);
if (curRec != sr) {
if (curRec != null) {
Slog.wtf(TAG, "Service " + sr + " in process " + app
@@ -3438,7 +3472,7 @@ public final class ActiveServices {
Slog.w(TAG, "Service crashed " + sr.crashCount
+ " times, stopping: " + sr);
EventLog.writeEvent(EventLogTags.AM_SERVICE_CRASHED_TOO_MUCH,
- sr.userId, sr.crashCount, sr.shortName, app.pid);
+ sr.userId, sr.crashCount, sr.shortInstanceName, app.pid);
bringDownServiceLocked(sr);
} else if (!allowRestart
|| !mAm.mUserController.isUserRunning(sr.userId, 0)) {
@@ -3644,7 +3678,7 @@ public final class ActiveServices {
mLastAnrDump = sw.toString();
mAm.mHandler.removeCallbacks(mLastAnrDumpClearer);
mAm.mHandler.postDelayed(mLastAnrDumpClearer, LAST_ANR_LIFETIME_DURATION_MSECS);
- anrMessage = "executing service " + timeout.shortName;
+ anrMessage = "executing service " + timeout.shortInstanceName;
} else {
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_TIMEOUT_MSG);
@@ -3690,7 +3724,8 @@ public final class ActiveServices {
final int userId = UserHandle.getUserId(applicationInfo.uid);
ServiceMap serviceMap = mServiceMap.get(userId);
if (serviceMap != null) {
- ArrayMap<ComponentName, ServiceRecord> servicesByName = serviceMap.mServicesByName;
+ ArrayMap<ComponentName, ServiceRecord> servicesByName
+ = serviceMap.mServicesByInstanceName;
for (int j = servicesByName.size() - 1; j >= 0; j--) {
ServiceRecord serviceRecord = servicesByName.valueAt(j);
if (applicationInfo.packageName.equals(serviceRecord.appInfo.packageName)) {
@@ -3761,9 +3796,9 @@ public final class ActiveServices {
final int[] users = mAm.mUserController.getUsers();
for (int user : users) {
ServiceMap smap = getServiceMapLocked(user);
- if (smap.mServicesByName.size() > 0) {
- for (int si=0; si<smap.mServicesByName.size(); si++) {
- ServiceRecord r = smap.mServicesByName.valueAt(si);
+ if (smap.mServicesByInstanceName.size() > 0) {
+ for (int si=0; si<smap.mServicesByInstanceName.size(); si++) {
+ ServiceRecord r = smap.mServicesByInstanceName.valueAt(si);
if (!matcher.match(r, r.name)) {
continue;
}
@@ -4164,7 +4199,7 @@ public final class ActiveServices {
}
long token = proto.start(ActiveServicesProto.SERVICES_BY_USERS);
proto.write(ActiveServicesProto.ServicesByUser.USER_ID, user);
- ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByName;
+ ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByInstanceName;
for (int i=0; i<alls.size(); i++) {
alls.valueAt(i).writeToProto(proto,
ActiveServicesProto.ServicesByUser.SERVICE_RECORDS);
@@ -4197,7 +4232,7 @@ public final class ActiveServices {
if (smap == null) {
continue;
}
- ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByName;
+ ArrayMap<ComponentName, ServiceRecord> alls = smap.mServicesByInstanceName;
for (int i=0; i<alls.size(); i++) {
ServiceRecord r1 = alls.valueAt(i);
@@ -4235,7 +4270,7 @@ public final class ActiveServices {
String innerPrefix = prefix + " ";
synchronized (mAm) {
pw.print(prefix); pw.print("SERVICE ");
- pw.print(r.shortName); pw.print(" ");
+ pw.print(r.shortInstanceName); pw.print(" ");
pw.print(Integer.toHexString(System.identityHashCode(r)));
pw.print(" pid=");
if (r.app != null) pw.println(r.app.pid);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d1392d0608c0..aa960828b15c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4820,6 +4820,10 @@ public class ActivityManagerService extends IActivityManager.Stub
String packageName, IBinder token, String resultWho,
int requestCode, Intent[] intents, String[] resolvedTypes,
int flags, Bundle bOptions, int userId) {
+
+ // NOTE: The service lock isn't held in this method because nothing in the method requires
+ // the service lock to be held.
+
enforceNotIsolatedCaller("getIntentSender");
// Refuse possible leaked file descriptors
if (intents != null) {
@@ -4851,43 +4855,41 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- synchronized(this) {
- int callingUid = Binder.getCallingUid();
- int origUserId = userId;
- userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
- type == ActivityManager.INTENT_SENDER_BROADCAST,
- ALLOW_NON_FULL, "getIntentSender", null);
- if (origUserId == UserHandle.USER_CURRENT) {
- // We don't want to evaluate this until the pending intent is
- // actually executed. However, we do want to always do the
- // security checking for it above.
- userId = UserHandle.USER_CURRENT;
- }
- try {
- if (callingUid != 0 && callingUid != SYSTEM_UID) {
- final int uid = AppGlobals.getPackageManager().getPackageUid(packageName,
- MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callingUid));
- if (!UserHandle.isSameApp(callingUid, uid)) {
- String msg = "Permission Denial: getIntentSender() from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid()
- + ", (need uid=" + uid + ")"
- + " is not allowed to send as package " + packageName;
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
- }
+ int callingUid = Binder.getCallingUid();
+ int origUserId = userId;
+ userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
+ type == ActivityManager.INTENT_SENDER_BROADCAST,
+ ALLOW_NON_FULL, "getIntentSender", null);
+ if (origUserId == UserHandle.USER_CURRENT) {
+ // We don't want to evaluate this until the pending intent is
+ // actually executed. However, we do want to always do the
+ // security checking for it above.
+ userId = UserHandle.USER_CURRENT;
+ }
+ try {
+ if (callingUid != 0 && callingUid != SYSTEM_UID) {
+ final int uid = AppGlobals.getPackageManager().getPackageUid(packageName,
+ MATCH_DEBUG_TRIAGED_MISSING, UserHandle.getUserId(callingUid));
+ if (!UserHandle.isSameApp(callingUid, uid)) {
+ String msg = "Permission Denial: getIntentSender() from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid()
+ + ", (need uid=" + uid + ")"
+ + " is not allowed to send as package " + packageName;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
}
+ }
- if (type == ActivityManager.INTENT_SENDER_ACTIVITY_RESULT) {
- return mAtmInternal.getIntentSender(type, packageName, callingUid, userId,
- token, resultWho, requestCode, intents, resolvedTypes, flags, bOptions);
- }
- return mPendingIntentController.getIntentSender(type, packageName, callingUid,
- userId, token, resultWho, requestCode, intents, resolvedTypes, flags,
- bOptions);
- } catch (RemoteException e) {
- throw new SecurityException(e);
+ if (type == ActivityManager.INTENT_SENDER_ACTIVITY_RESULT) {
+ return mAtmInternal.getIntentSender(type, packageName, callingUid, userId,
+ token, resultWho, requestCode, intents, resolvedTypes, flags, bOptions);
}
+ return mPendingIntentController.getIntentSender(type, packageName, callingUid,
+ userId, token, resultWho, requestCode, intents, resolvedTypes, flags,
+ bOptions);
+ } catch (RemoteException e) {
+ throw new SecurityException(e);
}
}
@@ -7002,7 +7004,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mCoreSettingsObserver = new CoreSettingsObserver(this);
mActivityTaskManager.installSystemProviders();
mDevelopmentSettingsObserver = new DevelopmentSettingsObserver();
- GlobalSettingsToPropertiesMapper.start(mContext.getContentResolver());
+ SettingsToPropertiesMapper.start(mContext.getContentResolver());
// Now that the settings provider is published we can consider sending
// in a rescue party.
@@ -13183,8 +13185,15 @@ public class ActivityManagerService extends IActivityManager.Stub
}
public int bindService(IApplicationThread caller, IBinder token, Intent service,
- String resolvedType, IServiceConnection connection, int flags, String callingPackage,
- int userId) throws TransactionTooLargeException {
+ String resolvedType, IServiceConnection connection, int flags,
+ String callingPackage, int userId) throws TransactionTooLargeException {
+ return bindIsolatedService(caller, token, service, resolvedType, connection, flags,
+ null, callingPackage, userId);
+ }
+
+ public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service,
+ String resolvedType, IServiceConnection connection, int flags, String instanceName,
+ String callingPackage, int userId) throws TransactionTooLargeException {
enforceNotIsolatedCaller("bindService");
// Refuse possible leaked file descriptors
@@ -13198,7 +13207,7 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized(this) {
return mServices.bindServiceLocked(caller, token, service,
- resolvedType, connection, flags, callingPackage, userId);
+ resolvedType, connection, flags, instanceName, callingPackage, userId);
}
}
@@ -15831,7 +15840,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mayBeTop = true;
mayBeTopType = "service";
mayBeTopSource = cr.binding.client;
- mayBeTopTarget = s.name;
+ mayBeTopTarget = s.instanceName;
clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
} else {
// Special handling for above-top states (persistent
@@ -15885,7 +15894,7 @@ public class ActivityManagerService extends IActivityManager.Stub
.REASON_SERVICE_IN_USE;
app.adjSource = cr.binding.client;
app.adjSourceProcState = clientProcState;
- app.adjTarget = s.name;
+ app.adjTarget = s.instanceName;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
+ ": " + app + ", due to " + cr.binding.client
@@ -15915,7 +15924,7 @@ public class ActivityManagerService extends IActivityManager.Stub
.REASON_SERVICE_IN_USE;
app.adjSource = a;
app.adjSourceProcState = procState;
- app.adjTarget = s.name;
+ app.adjTarget = s.instanceName;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
reportOomAdjMessageLocked(TAG_OOM_ADJ,
"Raise to service w/activity: " + app);
diff --git a/services/core/java/com/android/server/am/AppBindRecord.java b/services/core/java/com/android/server/am/AppBindRecord.java
index 4eaebd04a8ad..9870420cae13 100644
--- a/services/core/java/com/android/server/am/AppBindRecord.java
+++ b/services/core/java/com/android/server/am/AppBindRecord.java
@@ -59,12 +59,12 @@ final class AppBindRecord {
public String toString() {
return "AppBindRecord{"
+ Integer.toHexString(System.identityHashCode(this))
- + " " + service.shortName + ":" + client.processName + "}";
+ + " " + service.shortInstanceName + ":" + client.processName + "}";
}
void writeToProto(ProtoOutputStream proto, long fieldId) {
long token = proto.start(fieldId);
- proto.write(AppBindRecordProto.SERVICE_NAME, service.shortName);
+ proto.write(AppBindRecordProto.SERVICE_NAME, service.shortInstanceName);
proto.write(AppBindRecordProto.CLIENT_PROC_NAME, client.processName);
final int N = connections.size();
for (int i=0; i<N; i++) {
diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java
index 37d07bbda760..bfa3f66ce726 100644
--- a/services/core/java/com/android/server/am/ConnectionRecord.java
+++ b/services/core/java/com/android/server/am/ConnectionRecord.java
@@ -115,16 +115,16 @@ final class ConnectionRecord {
&& (binding.service.appInfo.uid != clientUid
|| !binding.service.processName.equals(clientProcessName))) {
ProcessStats.ProcessStateHolder holder = binding.service.app.pkgList.get(
- binding.service.name.getPackageName());
+ binding.service.instanceName.getPackageName());
if (holder == null) {
Slog.wtf(TAG_AM, "No package in referenced service "
- + binding.service.name.toShortString() + ": proc=" + binding.service.app);
+ + binding.service.shortInstanceName + ": proc=" + binding.service.app);
} else if (holder.pkg == null) {
Slog.wtf(TAG_AM, "Inactive holder in referenced service "
- + binding.service.name.toShortString() + ": proc=" + binding.service.app);
+ + binding.service.shortInstanceName + ": proc=" + binding.service.app);
} else {
association = holder.pkg.getAssociationStateLocked(holder.state,
- binding.service.name.getClassName()).startSource(clientUid,
+ binding.service.instanceName.getClassName()).startSource(clientUid,
clientProcessName);
}
@@ -202,7 +202,7 @@ final class ConnectionRecord {
if (serviceDead) {
sb.append("DEAD ");
}
- sb.append(binding.service.shortName);
+ sb.append(binding.service.shortInstanceName);
sb.append(":@");
sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder())));
sb.append('}');
@@ -223,7 +223,7 @@ final class ConnectionRecord {
proto.write(ConnectionRecordProto.FLAGS, ConnectionRecordProto.DEAD);
}
if (binding.service != null) {
- proto.write(ConnectionRecordProto.SERVICE_NAME, binding.service.shortName);
+ proto.write(ConnectionRecordProto.SERVICE_NAME, binding.service.shortInstanceName);
}
proto.end(token);
}
diff --git a/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
deleted file mode 100644
index 1366c218299e..000000000000
--- a/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.am;
-
-import android.content.ContentResolver;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Build;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Slog;
-import android.view.ThreadedRenderer;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Preconditions;
-
-/**
- * Maps global system settings to system properties.
- * <p>The properties are dynamically updated when settings change.
- */
-class GlobalSettingsToPropertiesMapper {
-
- private static final String TAG = "GlobalSettingsToPropertiesMapper";
-
- // List mapping entries in the following format:
- // {Settings.Global.SETTING_NAME, "system_property_name"}
- // Important: Property being added should be whitelisted by SELinux policy or have one of the
- // already whitelisted prefixes in system_server.te, e.g. sys.
- private static final String[][] sGlobalSettingsMapping = new String[][] {
- {Settings.Global.SYS_VDSO, "sys.vdso"},
- {Settings.Global.FPS_DEVISOR, ThreadedRenderer.DEBUG_FPS_DIVISOR},
- {Settings.Global.DISPLAY_PANEL_LPM, "sys.display_panel_lpm"},
- {Settings.Global.SYS_UIDCPUPOWER, "sys.uidcpupower"},
- {Settings.Global.SYS_TRACED, "sys.traced.enable_override"},
- };
-
-
- private final ContentResolver mContentResolver;
- private final String[][] mGlobalSettingsMapping;
-
- @VisibleForTesting
- GlobalSettingsToPropertiesMapper(ContentResolver contentResolver,
- String[][] globalSettingsMapping) {
- mContentResolver = contentResolver;
- mGlobalSettingsMapping = globalSettingsMapping;
- }
-
- void updatePropertiesFromGlobalSettings() {
- for (String[] entry : mGlobalSettingsMapping) {
- final String settingName = entry[0];
- final String propName = entry[1];
- Uri settingUri = Settings.Global.getUriFor(settingName);
- Preconditions.checkNotNull(settingUri, "Setting " + settingName + " not found");
- ContentObserver co = new ContentObserver(null) {
- @Override
- public void onChange(boolean selfChange) {
- updatePropertyFromSetting(settingName, propName);
- }
- };
- updatePropertyFromSetting(settingName, propName);
- mContentResolver.registerContentObserver(settingUri, false, co);
- }
- }
-
- public static void start(ContentResolver contentResolver) {
- new GlobalSettingsToPropertiesMapper(contentResolver, sGlobalSettingsMapping)
- .updatePropertiesFromGlobalSettings();
- }
-
- private String getGlobalSetting(String name) {
- return Settings.Global.getString(mContentResolver, name);
- }
-
- private void setProperty(String key, String value) {
- // Check if need to clear the property
- if (value == null) {
- // It's impossible to remove system property, therefore we check previous value to
- // avoid setting an empty string if the property wasn't set.
- if (TextUtils.isEmpty(systemPropertiesGet(key))) {
- return;
- }
- value = "";
- }
- try {
- systemPropertiesSet(key, value);
- } catch (Exception e) {
- // Failure to set a property can be caused by SELinux denial. This usually indicates
- // that the property wasn't whitelisted in sepolicy.
- // No need to report it on all user devices, only on debug builds.
- if (Build.IS_DEBUGGABLE) {
- Slog.wtf(TAG, "Unable to set property " + key + " value '" + value + "'", e);
- } else {
- Slog.e(TAG, "Unable to set property " + key + " value '" + value + "'", e);
- }
- }
- }
-
- @VisibleForTesting
- protected String systemPropertiesGet(String key) {
- return SystemProperties.get(key);
- }
-
- @VisibleForTesting
- protected void systemPropertiesSet(String key, String value) {
- SystemProperties.set(key, value);
- }
-
- @VisibleForTesting
- void updatePropertyFromSetting(String settingName, String propName) {
- String settingValue = getGlobalSetting(settingName);
- setProperty(propName, settingValue);
- }
-}
diff --git a/services/core/java/com/android/server/am/IntentBindRecord.java b/services/core/java/com/android/server/am/IntentBindRecord.java
index 839b6e1bd634..90aef3efea46 100644
--- a/services/core/java/com/android/server/am/IntentBindRecord.java
+++ b/services/core/java/com/android/server/am/IntentBindRecord.java
@@ -99,7 +99,7 @@ final class IntentBindRecord {
if ((collectFlags()&Context.BIND_AUTO_CREATE) != 0) {
sb.append("CR ");
}
- sb.append(service.shortName);
+ sb.append(service.shortInstanceName);
sb.append(':');
if (intent != null) {
intent.getIntent().toShortString(sb, false, false, false, false);
diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS
index 79c98e550774..5208ca5eb0db 100644
--- a/services/core/java/com/android/server/am/OWNERS
+++ b/services/core/java/com/android/server/am/OWNERS
@@ -27,4 +27,4 @@ toddke@google.com
michaelwr@google.com
narayan@google.com
-per-file GlobalSettingsToPropertiesMapper.java = omakoto@google.com, svetoslavganov@google.com, yamasani@google.com
+per-file SettingsToPropertiesMapper.java = omakoto@google.com, svetoslavganov@google.com, yamasani@google.com
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index d8f94c933ac8..09f8c3eee3b6 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -70,7 +70,8 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
final ActivityManagerService ams;
final BatteryStatsImpl.Uid.Pkg.Serv stats;
final ComponentName name; // service component.
- final String shortName; // name.flattenToShortString().
+ final ComponentName instanceName; // service component's per-instance name.
+ final String shortInstanceName; // instanceName.flattenToShortString().
final Intent.FilterComparison intent;
// original intent used to find service.
final ServiceInfo serviceInfo;
@@ -190,7 +191,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
StringBuilder sb = new StringBuilder(128);
sb.append("ServiceRecord{")
.append(Integer.toHexString(System.identityHashCode(sr)))
- .append(' ').append(sr.shortName)
+ .append(' ').append(sr.shortInstanceName)
.append(" StartItem ")
.append(Integer.toHexString(System.identityHashCode(this)))
.append(" id=").append(id).append('}');
@@ -235,7 +236,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
void writeToProto(ProtoOutputStream proto, long fieldId) {
long token = proto.start(fieldId);
- proto.write(ServiceRecordProto.SHORT_NAME, this.shortName);
+ proto.write(ServiceRecordProto.SHORT_NAME, this.shortInstanceName);
proto.write(ServiceRecordProto.IS_RUNNING, app != null);
if (app != null) {
proto.write(ServiceRecordProto.PID, app.pid);
@@ -448,12 +449,14 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
ServiceRecord(ActivityManagerService ams,
BatteryStatsImpl.Uid.Pkg.Serv servStats, ComponentName name,
+ ComponentName instanceName,
Intent.FilterComparison intent, ServiceInfo sInfo, boolean callerIsFg,
Runnable restarter) {
this.ams = ams;
this.stats = servStats;
this.name = name;
- shortName = name.flattenToShortString();
+ this.instanceName = instanceName;
+ shortInstanceName = instanceName.flattenToShortString();
this.intent = intent;
serviceInfo = sInfo;
appInfo = sInfo.applicationInfo;
@@ -618,7 +621,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
// those dirty apps we will create a notification clearly
// blaming the app.
Slog.v(TAG, "Attempted to start a foreground service ("
- + name
+ + shortInstanceName
+ ") with a broken notification (no icon: "
+ localForegroundNoti
+ ")");
@@ -701,7 +704,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
Slog.w(TAG, "Error showing notification for service", e);
// If it gave us a garbage notification, it doesn't
// get to be foreground.
- ams.setServiceForeground(name, ServiceRecord.this,
+ ams.setServiceForeground(instanceName, ServiceRecord.this,
0, null, 0);
ams.crashApplication(appUid, appPid, localPackageName, -1,
"Bad notification for startForeground: " + e);
@@ -773,7 +776,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
sb.append("ServiceRecord{")
.append(Integer.toHexString(System.identityHashCode(this)))
.append(" u").append(userId)
- .append(' ').append(shortName).append('}');
+ .append(' ').append(shortInstanceName).append('}');
return stringName = sb.toString();
}
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
new file mode 100644
index 000000000000..a5848ca0235a
--- /dev/null
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.content.ContentResolver;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Build;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashSet;
+
+/**
+ * Maps system settings to system properties.
+ * <p>The properties are dynamically updated when settings change.
+ */
+class SettingsToPropertiesMapper {
+
+ private static final String TAG = "SettingsToPropertiesMapper";
+
+ private static final String SYSTEM_PROPERTY_PREFIX = "persist.device_config.";
+
+ private static final String RESET_PERFORMED_PROPERTY = "device_config.reset_performed";
+
+ private static final String RESET_RECORD_FILE_PATH =
+ "/data/server_configurable_flags/reset_flags";
+
+ private static final String SYSTEM_PROPERTY_VALID_CHARACTERS_REGEX = "^[\\w\\.\\-@:]*$";
+
+ private static final String SYSTEM_PROPERTY_INVALID_SUBSTRING = "..";
+
+ private static final int SYSTEM_PROPERTY_MAX_LENGTH = 92;
+
+ // experiment flags added to Global.Settings(before new "Config" provider table is available)
+ // will be added under this category.
+ private static final String GLOBAL_SETTINGS_CATEGORY = "global_settings";
+
+ // Add the global setting you want to push to native level as experiment flag into this list.
+ //
+ // NOTE: please grant write permission system property prefix
+ // with format persist.experiment.[experiment_category_name]. in system_server.te and grant read
+ // permission in the corresponding .te file your feature belongs to.
+ @VisibleForTesting
+ static final String[] sGlobalSettings = new String[] {
+ };
+
+ @VisibleForTesting
+ static final String[] sDeviceConfigScopes = new String[] {
+ };
+
+ private final String[] mGlobalSettings;
+
+ private final String[] mDeviceConfigScopes;
+
+ private final ContentResolver mContentResolver;
+
+ @VisibleForTesting
+ protected SettingsToPropertiesMapper(ContentResolver contentResolver,
+ String[] globalSettings,
+ String[] deviceConfigScopes) {
+ mContentResolver = contentResolver;
+ mGlobalSettings = globalSettings;
+ mDeviceConfigScopes = deviceConfigScopes;
+ }
+
+ @VisibleForTesting
+ void updatePropertiesFromSettings() {
+ for (String globalSetting : mGlobalSettings) {
+ Uri settingUri = Settings.Global.getUriFor(globalSetting);
+ String propName = makePropertyName(GLOBAL_SETTINGS_CATEGORY, globalSetting);
+ if (settingUri == null) {
+ log("setting uri is null for globalSetting " + globalSetting);
+ continue;
+ }
+ if (propName == null) {
+ log("invalid prop name for globalSetting " + globalSetting);
+ continue;
+ }
+
+ ContentObserver co = new ContentObserver(null) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updatePropertyFromSetting(globalSetting, propName, true);
+ }
+ };
+
+ // only updating on starting up when no native flags reset is performed during current
+ // booting.
+ if (!isNativeFlagsResetPerformed()) {
+ updatePropertyFromSetting(globalSetting, propName, true);
+ }
+ mContentResolver.registerContentObserver(settingUri, false, co);
+ }
+
+ // TODO: address sDeviceConfigScopes after DeviceConfig APIs are available.
+ }
+
+ public static SettingsToPropertiesMapper start(ContentResolver contentResolver) {
+ SettingsToPropertiesMapper mapper = new SettingsToPropertiesMapper(
+ contentResolver, sGlobalSettings, sDeviceConfigScopes);
+ mapper.updatePropertiesFromSettings();
+ return mapper;
+ }
+
+ /**
+ * If native level flags reset has been performed as an attempt to recover from a crash loop
+ * during current device booting.
+ * @return
+ */
+ public boolean isNativeFlagsResetPerformed() {
+ String value = systemPropertiesGet(RESET_PERFORMED_PROPERTY);
+ return "true".equals(value);
+ }
+
+ /**
+ * return an array of native flag categories under which flags got reset during current device
+ * booting.
+ * @return
+ */
+ public String[] getResetNativeCategories() {
+ if (!isNativeFlagsResetPerformed()) {
+ return new String[0];
+ }
+
+ String content = getResetFlagsFileContent();
+ if (TextUtils.isEmpty(content)) {
+ return new String[0];
+ }
+
+ String[] property_names = content.split(";");
+ HashSet<String> categories = new HashSet<>();
+ for (String property_name : property_names) {
+ String[] segments = property_name.split("\\.");
+ if (segments.length < 3) {
+ log("failed to extract category name from property " + property_name);
+ continue;
+ }
+ categories.add(segments[2]);
+ }
+ return categories.toArray(new String[0]);
+ }
+
+ /**
+ * system property name constructing rule: "persist.device_config.[category_name].[flag_name]".
+ * If the name contains invalid characters or substrings for system property name,
+ * will return null.
+ * @param categoryName
+ * @param flagName
+ * @return
+ */
+ @VisibleForTesting
+ static String makePropertyName(String categoryName, String flagName) {
+ String propertyName = SYSTEM_PROPERTY_PREFIX + categoryName + "." + flagName;
+
+ if (!propertyName.matches(SYSTEM_PROPERTY_VALID_CHARACTERS_REGEX)
+ || propertyName.contains(SYSTEM_PROPERTY_INVALID_SUBSTRING)) {
+ return null;
+ }
+
+ return propertyName;
+ }
+
+ private String getSetting(String name, boolean isGlobalSetting) {
+ if (isGlobalSetting) {
+ return Settings.Global.getString(mContentResolver, name);
+ } else {
+ // TODO: complete the code after DeviceConfig APIs implemented.
+ return null;
+ }
+ }
+
+ private void setProperty(String key, String value) {
+ // Check if need to clear the property
+ if (value == null) {
+ // It's impossible to remove system property, therefore we check previous value to
+ // avoid setting an empty string if the property wasn't set.
+ if (TextUtils.isEmpty(systemPropertiesGet(key))) {
+ return;
+ }
+ value = "";
+ } else if (value.length() > SYSTEM_PROPERTY_MAX_LENGTH) {
+ log(value + " exceeds system property max length.");
+ return;
+ }
+
+ try {
+ systemPropertiesSet(key, value);
+ } catch (Exception e) {
+ // Failure to set a property can be caused by SELinux denial. This usually indicates
+ // that the property wasn't whitelisted in sepolicy.
+ // No need to report it on all user devices, only on debug builds.
+ log("Unable to set property " + key + " value '" + value + "'", e);
+ }
+ }
+
+ private static void log(String msg, Exception e) {
+ if (Build.IS_DEBUGGABLE) {
+ Slog.wtf(TAG, msg, e);
+ } else {
+ Slog.e(TAG, msg, e);
+ }
+ }
+
+ private static void log(String msg) {
+ if (Build.IS_DEBUGGABLE) {
+ Slog.wtf(TAG, msg);
+ } else {
+ Slog.e(TAG, msg);
+ }
+ }
+
+ @VisibleForTesting
+ protected String systemPropertiesGet(String key) {
+ return SystemProperties.get(key);
+ }
+
+ @VisibleForTesting
+ protected void systemPropertiesSet(String key, String value) {
+ SystemProperties.set(key, value);
+ }
+
+ @VisibleForTesting
+ protected String getResetFlagsFileContent() {
+ String content = null;
+ try {
+ File reset_flag_file = new File(RESET_RECORD_FILE_PATH);
+ BufferedReader br = new BufferedReader(new FileReader(reset_flag_file));
+ content = br.readLine();
+
+ br.close();
+ } catch (IOException ioe) {
+ log("failed to read file " + RESET_RECORD_FILE_PATH, ioe);
+ }
+ return content;
+ }
+
+ @VisibleForTesting
+ void updatePropertyFromSetting(String settingName, String propName, boolean isGlobalSetting) {
+ String settingValue = getSetting(settingName, isGlobalSetting);
+ setProperty(propName, settingValue);
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 278c55f74ebb..5f09189bd84a 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -246,9 +246,20 @@ public class BiometricService extends SystemService {
public void authenticate(IBinder token, long sessionId, int userId,
IBiometricServiceReceiver receiver, int flags, String opPackageName,
Bundle bundle, IBiometricPromptReceiver dialogReceiver) throws RemoteException {
- // Check the USE_BIOMETRIC permission here. In the BiometricServiceBase, check do the
- // AppOps and foreground check.
- checkPermission();
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+ final int callingUserId = UserHandle.getCallingUserId();
+
+ // In the BiometricServiceBase, check do the AppOps and foreground check.
+ if (userId == callingUserId) {
+ // Check the USE_BIOMETRIC permission here.
+ checkPermission();
+ } else {
+ // Only allow internal clients to authenticate with a different userId
+ Slog.w(TAG, "User " + callingUserId + " is requesting authentication of userid: "
+ + userId);
+ checkInternalPermission();
+ }
if (token == null || receiver == null || opPackageName == null || bundle == null
|| dialogReceiver == null) {
@@ -262,10 +273,6 @@ public class BiometricService extends SystemService {
checkInternalPermission();
}
- final int callingUid = Binder.getCallingUid();
- final int callingPid = Binder.getCallingPid();
- final int callingUserId = UserHandle.getCallingUserId();
-
mHandler.post(() -> {
final Pair<Integer, Integer> result = checkAndGetBiometricModality(callingUserId);
final int modality = result.first;
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index a769590447ab..65537adccbc6 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -55,6 +55,7 @@ import android.util.SparseArray;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.intelligence.IntelligenceManagerInternal;
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -157,6 +158,7 @@ public class ClipboardService extends SystemService {
private final IUserManager mUm;
private final PackageManager mPm;
private final AppOpsManager mAppOps;
+ private final IntelligenceManagerInternal mIm;
private final IBinder mPermissionOwner;
private HostClipboardMonitor mHostClipboardMonitor = null;
private Thread mHostMonitorThread = null;
@@ -176,6 +178,7 @@ public class ClipboardService extends SystemService {
mPm = getContext().getPackageManager();
mUm = (IUserManager) ServiceManager.getService(Context.USER_SERVICE);
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
+ mIm = LocalServices.getService(IntelligenceManagerInternal.class);
final IBinder permOwner = mUgmInternal.newUriPermissionOwner("clipboard");
mPermissionOwner = permOwner;
if (IS_EMULATOR) {
@@ -635,8 +638,9 @@ public class ClipboardService extends SystemService {
return true;
}
// The default IME is always allowed to access the clipboard.
+ int userId = UserHandle.getUserId(callingUid);
String defaultIme = Settings.Secure.getStringForUser(getContext().getContentResolver(),
- Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.getUserId(callingUid));
+ Settings.Secure.DEFAULT_INPUT_METHOD, userId);
if (!TextUtils.isEmpty(defaultIme)) {
final String imePkg = ComponentName.unflattenFromString(defaultIme).getPackageName();
if (imePkg.equals(callingPackage)) {
@@ -646,13 +650,18 @@ public class ClipboardService extends SystemService {
switch (op) {
case AppOpsManager.OP_READ_CLIPBOARD:
- // Clipboard can only be read by applications with focus.
- boolean uidFocused = mWm.isUidFocused(callingUid);
- if (!uidFocused) {
+ // Clipboard can only be read by applications with focus..
+ boolean allowed = mWm.isUidFocused(callingUid);
+ if (!allowed && mIm != null) {
+ // ...or the Intelligence Service
+ allowed = mIm.isIntelligenceServiceForUser(callingUid, userId);
+ }
+ if (!allowed) {
Slog.e(TAG, "Denying clipboard access to " + callingPackage
- + ", application is not in focus.");
+ + ", application is not in focus neither is the IntelligeService for "
+ + "user " + userId);
}
- return uidFocused;
+ return allowed;
case AppOpsManager.OP_WRITE_CLIPBOARD:
// Writing is allowed without focus.
return true;
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index c20079e8a685..3a31c9c5e05f 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -72,6 +72,8 @@ import android.view.IInputFilter;
import android.view.IInputFilterHost;
import android.view.IWindow;
import android.view.InputChannel;
+import android.view.InputApplicationHandle;
+import android.view.InputWindowHandle;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.KeyEvent;
@@ -197,7 +199,7 @@ public class InputManagerService extends IInputManager.Stub
private static native boolean nativeHasKeys(long ptr,
int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists);
private static native void nativeRegisterInputChannel(long ptr, InputChannel inputChannel,
- InputWindowHandle inputWindowHandle, int displayId);
+ int displayId);
private static native void nativeUnregisterInputChannel(long ptr, InputChannel inputChannel);
private static native void nativeSetInputFilterEnabled(long ptr, boolean enable);
private static native int nativeInjectInputEvent(long ptr, InputEvent event,
@@ -486,8 +488,7 @@ public class InputManagerService extends IInputManager.Stub
}
InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
- // Register channel for monitor.
- nativeRegisterInputChannel(mPtr, inputChannels[0], null, displayId);
+ nativeRegisterInputChannel(mPtr, inputChannels[0], displayId);
inputChannels[0].dispose(); // don't need to retain the Java object reference
return inputChannels[1];
}
@@ -498,14 +499,17 @@ public class InputManagerService extends IInputManager.Stub
* @param inputWindowHandle The handle of the input window associated with the
* input channel, or null if none.
*/
- public void registerInputChannel(InputChannel inputChannel,
- InputWindowHandle inputWindowHandle) {
+ public void registerInputChannel(InputChannel inputChannel, IBinder token) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null.");
}
- // Register channel for normal.
- nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, Display.INVALID_DISPLAY);
+ if (token == null) {
+ token = new Binder();
+ }
+ inputChannel.setToken(token);
+
+ nativeRegisterInputChannel(mPtr, inputChannel, Display.INVALID_DISPLAY);
}
/**
@@ -1791,15 +1795,15 @@ public class InputManagerService extends IInputManager.Stub
}
// Native callback.
- private void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
- mWindowManagerCallbacks.notifyInputChannelBroken(inputWindowHandle);
+ private void notifyInputChannelBroken(IBinder token) {
+ mWindowManagerCallbacks.notifyInputChannelBroken(token);
}
// Native callback.
private long notifyANR(InputApplicationHandle inputApplicationHandle,
- InputWindowHandle inputWindowHandle, String reason) {
+ IBinder token, String reason) {
return mWindowManagerCallbacks.notifyANR(
- inputApplicationHandle, inputWindowHandle, reason);
+ inputApplicationHandle, token, reason);
}
// Native callback.
@@ -1830,13 +1834,13 @@ public class InputManagerService extends IInputManager.Stub
}
// Native callback.
- private long interceptKeyBeforeDispatching(InputWindowHandle focus,
+ private long interceptKeyBeforeDispatching(IBinder focus,
KeyEvent event, int policyFlags) {
return mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);
}
// Native callback.
- private KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
+ private KeyEvent dispatchUnhandledKey(IBinder focus,
KeyEvent event, int policyFlags) {
return mWindowManagerCallbacks.dispatchUnhandledKey(focus, event, policyFlags);
}
@@ -1987,19 +1991,19 @@ public class InputManagerService extends IInputManager.Stub
public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered);
- public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle);
+ public void notifyInputChannelBroken(IBinder token);
public long notifyANR(InputApplicationHandle inputApplicationHandle,
- InputWindowHandle inputWindowHandle, String reason);
+ IBinder token, String reason);
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags);
- public long interceptKeyBeforeDispatching(InputWindowHandle focus,
+ public long interceptKeyBeforeDispatching(IBinder token,
KeyEvent event, int policyFlags);
- public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
+ public KeyEvent dispatchUnhandledKey(IBinder token,
KeyEvent event, int policyFlags);
public int getPointerLayer();
diff --git a/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java b/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java
new file mode 100644
index 000000000000..0ed56ff4ca13
--- /dev/null
+++ b/services/core/java/com/android/server/intelligence/IntelligenceManagerInternal.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.intelligence;
+
+import android.annotation.UserIdInt;
+
+/**
+ * Intelligence Manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class IntelligenceManagerInternal {
+
+ /**
+ * Checks whether the given {@code uid} owns the
+ * {@link android.service.intelligence.IntelligenceService} implementation associated with the
+ * given {@code userId}.
+ */
+ public abstract boolean isIntelligenceServiceForUser(int uid, @UserIdInt int userId);
+}
diff --git a/services/core/java/com/android/server/location/ContextHubClientBroker.java b/services/core/java/com/android/server/location/ContextHubClientBroker.java
index 002d4e1049fb..6612d0264aff 100644
--- a/services/core/java/com/android/server/location/ContextHubClientBroker.java
+++ b/services/core/java/com/android/server/location/ContextHubClientBroker.java
@@ -40,6 +40,8 @@ import java.util.function.Supplier;
* notification callbacks. This class implements the IContextHubClient object, and the implemented
* APIs must be thread-safe.
*
+ * TODO: Consider refactoring this class via inheritance
+ *
* @hide
*/
public class ContextHubClientBroker extends IContextHubClient.Stub
@@ -92,7 +94,7 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
/*
* The PendingIntent registered with this client.
*/
- private final PendingIntentRequest mPendingIntentRequest = new PendingIntentRequest();
+ private final PendingIntentRequest mPendingIntentRequest;
/*
* Helper class to manage registered PendingIntent requests from the client.
@@ -130,41 +132,31 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
public void clear() {
mPendingIntent = null;
}
+ }
- public boolean register(PendingIntent pendingIntent, long nanoAppId) {
- boolean success = false;
- if (hasPendingIntent()) {
- Log.e(TAG, "Failed to register PendingIntent: registered PendingIntent exists");
- } else {
- mNanoAppId = nanoAppId;
- mPendingIntent = pendingIntent;
- success = true;
- }
-
- return success;
- }
-
- public boolean unregister(PendingIntent pendingIntent) {
- boolean success = false;
- if (!hasPendingIntent() || !mPendingIntent.equals(pendingIntent)) {
- Log.e(TAG, "Failed to unregister PendingIntent: PendingIntent is not registered");
- } else {
- mPendingIntent = null;
- success = true;
- }
-
- return success;
- }
+ /* package */ ContextHubClientBroker(
+ Context context, IContexthub contextHubProxy, ContextHubClientManager clientManager,
+ ContextHubInfo contextHubInfo, short hostEndPointId,
+ IContextHubClientCallback callback) {
+ mContext = context;
+ mContextHubProxy = contextHubProxy;
+ mClientManager = clientManager;
+ mAttachedContextHubInfo = contextHubInfo;
+ mHostEndPointId = hostEndPointId;
+ mCallbackInterface = callback;
+ mPendingIntentRequest = new PendingIntentRequest();
}
/* package */ ContextHubClientBroker(
Context context, IContexthub contextHubProxy, ContextHubClientManager clientManager,
- ContextHubInfo contextHubInfo, short hostEndPointId) {
+ ContextHubInfo contextHubInfo, short hostEndPointId, PendingIntent pendingIntent,
+ long nanoAppId) {
mContext = context;
mContextHubProxy = contextHubProxy;
mClientManager = clientManager;
mAttachedContextHubInfo = contextHubInfo;
mHostEndPointId = hostEndPointId;
+ mPendingIntentRequest = new PendingIntentRequest(pendingIntent, nanoAppId);
}
/**
@@ -179,11 +171,7 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
ContextHubServiceUtil.checkPermissions(mContext);
int result;
- IContextHubClientCallback callback = null;
- synchronized (this) {
- callback = mCallbackInterface;
- }
- if (callback != null) {
+ if (isRegistered()) {
ContextHubMsg messageToNanoApp =
ContextHubServiceUtil.createHidlContextHubMessage(mHostEndPointId, message);
@@ -204,64 +192,16 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
}
/**
- * @param pendingIntent the intent to register
- * @param nanoAppId the ID of the nanoapp to send events for
- * @return true on success, false otherwise
- */
- @Override
- public boolean registerIntent(PendingIntent pendingIntent, long nanoAppId) {
- ContextHubServiceUtil.checkPermissions(mContext);
- if (mClientManager.isPendingIntentRegistered(pendingIntent)) {
- Log.e(TAG, "Failed to register PendingIntent: already registered");
- return false;
- }
-
- boolean success = false;
- synchronized (this) {
- if (mCallbackInterface == null) {
- Log.e(TAG, "Failed to register PendingIntent: client connection is closed");
- } else {
- success = mPendingIntentRequest.register(pendingIntent, nanoAppId);
- }
- }
-
- return success;
- }
-
- /**
- * @param pendingIntent the intent to unregister
- * @return true on success, false otherwise
- */
- @Override
- public boolean unregisterIntent(PendingIntent pendingIntent) {
- ContextHubServiceUtil.checkPermissions(mContext);
-
- boolean success = false;
- synchronized (this) {
- success = mPendingIntentRequest.unregister(pendingIntent);
- if (mCallbackInterface == null) {
- close();
- }
- }
-
- return success;
- }
-
- /**
* Closes the connection for this client with the service.
+ *
+ * If the client has a PendingIntent registered, this method also unregisters it.
*/
@Override
public void close() {
synchronized (this) {
- if (mCallbackInterface != null) {
- mCallbackInterface.asBinder().unlinkToDeath(this, 0 /* flags */);
- mCallbackInterface = null;
- }
- if (!mPendingIntentRequest.hasPendingIntent() && mRegistered) {
- mClientManager.unregisterClient(mHostEndPointId);
- mRegistered = false;
- }
+ mPendingIntentRequest.clear();
}
+ onClientExit();
}
/**
@@ -269,38 +209,7 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
*/
@Override
public void binderDied() {
- close();
- }
-
- /**
- * Sets the callback interface for this client, only if the callback is currently unregistered.
- *
- * Also attaches a death recipient to a ContextHubClientBroker object. If unsuccessful, the
- * connection is closed.
- *
- * @param callback the callback interface
- * @return true if the callback was successfully set, false otherwise
- *
- * @throws IllegalStateException if the client has already been registered to a callback
- */
- /* package */
- synchronized boolean setCallback(IContextHubClientCallback callback) {
- boolean success = false;
- if (mCallbackInterface != null) {
- throw new IllegalStateException("Client is already registered with a callback");
- } else {
- mCallbackInterface = callback;
- try {
- mCallbackInterface.asBinder().linkToDeath(this, 0 /* flags */);
- success = true;
- } catch (RemoteException e) {
- // The client process has died, so we close the connection.
- Log.e(TAG, "Failed to attach death recipient to client");
- close();
- }
- }
-
- return success;
+ onClientExit();
}
/**
@@ -375,15 +284,30 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
}
/**
- * @param intent the PendingIntent to compare to
+ * @param intent the PendingIntent to compare to
+ * @param nanoAppId the ID of the nanoapp of the PendingIntent to compare to
* @return true if the given PendingIntent is currently registered, false otherwise
*/
- /* package */ boolean hasPendingIntent(PendingIntent intent) {
+ /* package */ boolean hasPendingIntent(PendingIntent intent, long nanoAppId) {
PendingIntent pendingIntent = null;
+ long intentNanoAppId;
synchronized (this) {
pendingIntent = mPendingIntentRequest.getPendingIntent();
+ intentNanoAppId = mPendingIntentRequest.getNanoAppId();
+ }
+ return (pendingIntent != null) && pendingIntent.equals(intent)
+ && intentNanoAppId == nanoAppId;
+ }
+
+ /**
+ * Attaches the death recipient to the callback interface object, if any.
+ *
+ * @throws RemoteException if the client process already died
+ */
+ /* package */ void attachDeathRecipient() throws RemoteException {
+ if (mCallbackInterface != null) {
+ mCallbackInterface.asBinder().linkToDeath(this, 0 /* flags */);
}
- return (pendingIntent != null) && pendingIntent.equals(intent);
}
/**
@@ -446,11 +370,29 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
// The PendingIntent is no longer valid
Log.w(TAG, "PendingIntent has been canceled, unregistering from client"
+ " (host endpoint ID " + mHostEndPointId + ")");
- mPendingIntentRequest.clear();
- if (mCallbackInterface == null) {
- close();
- }
+ close();
}
}
}
+
+ /**
+ * @return true if the client is still registered with the service, false otherwise
+ */
+ private synchronized boolean isRegistered() {
+ return mRegistered;
+ }
+
+ /**
+ * Invoked when a client exits either explicitly or by binder death.
+ */
+ private synchronized void onClientExit() {
+ if (mCallbackInterface != null) {
+ mCallbackInterface.asBinder().unlinkToDeath(this, 0 /* flags */);
+ mCallbackInterface = null;
+ }
+ if (!mPendingIntentRequest.hasPendingIntent() && mRegistered) {
+ mClientManager.unregisterClient(mHostEndPointId);
+ mRegistered = false;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/location/ContextHubClientManager.java b/services/core/java/com/android/server/location/ContextHubClientManager.java
index fe93a1a0f613..7293440cd439 100644
--- a/services/core/java/com/android/server/location/ContextHubClientManager.java
+++ b/services/core/java/com/android/server/location/ContextHubClientManager.java
@@ -24,6 +24,7 @@ import android.hardware.location.ContextHubInfo;
import android.hardware.location.IContextHubClient;
import android.hardware.location.IContextHubClientCallback;
import android.hardware.location.NanoAppMessage;
+import android.os.RemoteException;
import android.util.Log;
import java.util.concurrent.ConcurrentHashMap;
@@ -68,7 +69,7 @@ import java.util.function.Consumer;
/*
* The next host endpoint ID to start iterating for the next available host endpoint ID.
*/
- private int mNextHostEndpointId = 0;
+ private int mNextHostEndPointId = 0;
/* package */ ContextHubClientManager(
Context context, IContexthub contextHubProxy) {
@@ -88,9 +89,22 @@ import java.util.function.Consumer;
*/
/* package */ IContextHubClient registerClient(
IContextHubClientCallback clientCallback, ContextHubInfo contextHubInfo) {
- ContextHubClientBroker broker = createNewClientBroker(contextHubInfo);
- if (!broker.setCallback(clientCallback)) {
- return null; // Client process has died, so we return null
+ ContextHubClientBroker broker;
+ synchronized (this) {
+ short hostEndPointId = getHostEndPointId();
+ broker = new ContextHubClientBroker(
+ mContext, mContextHubProxy, this /* clientManager */, contextHubInfo,
+ hostEndPointId, clientCallback);
+ mHostEndPointIdToClientMap.put(hostEndPointId, broker);
+ }
+
+ try {
+ broker.attachDeathRecipient();
+ } catch (RemoteException e) {
+ // The client process has died, so we close the connection and return null
+ Log.e(TAG, "Failed to attach death recipient to client");
+ broker.close();
+ return null;
}
Log.d(TAG, "Registered client with host endpoint ID " + broker.getHostEndPointId());
@@ -98,32 +112,36 @@ import java.util.function.Consumer;
}
/**
- * Binds a existing and registered client with a new callback interface, provided a previously
- * registered PendingIntent.
+ * Registers a new client with the service.
*
- * @param pendingIntent a previously registered PendingIntent for a registered client
- * @param clientCallback the callback interface of the client to bind to
- * @param contextHubId the ID of the hub this client is attached to
+ * @param pendingIntent the callback interface of the client to register
+ * @param contextHubInfo the object describing the hub this client is attached to
+ * @param nanoAppId the ID of the nanoapp to receive Intent events for
*
* @return the client interface
*
- * @throws IllegalArgumentException if no matching client is found
- * @throws IllegalStateException if the client has already been registered to a callback
+ * @throws IllegalArgumentException the PendingIntent was already registered for a different
+ * ContextHubClient
+ * @throws IllegalStateException if there were too many registered clients at the service
*/
- /* package */ IContextHubClient bindClient(
- PendingIntent pendingIntent, IContextHubClientCallback clientCallback,
- int contextHubId) {
- ContextHubClientBroker broker = getClientBroker(pendingIntent, contextHubId);
- if (broker == null) {
- throw new IllegalArgumentException("Could not find client of Context Hub (ID = "
- + contextHubId + ") with PendingIntent");
- }
-
- if (!broker.setCallback(clientCallback)) {
- return null; // Client process has died, so we return null
+ /* package */ IContextHubClient registerClient(
+ ContextHubInfo contextHubInfo, PendingIntent pendingIntent, long nanoAppId) {
+ ContextHubClientBroker broker;
+ String registerString = "Regenerated";
+ synchronized (this) {
+ broker = getClientBroker(contextHubInfo.getId(), pendingIntent, nanoAppId);
+
+ if (broker == null) {
+ short hostEndPointId = getHostEndPointId();
+ broker = new ContextHubClientBroker(
+ mContext, mContextHubProxy, this /* clientManager */, contextHubInfo,
+ hostEndPointId, pendingIntent, nanoAppId);
+ mHostEndPointIdToClientMap.put(hostEndPointId, broker);
+ registerString = "Registered";
+ }
}
- Log.d(TAG, "Re-registered client with host endpoint ID " + broker.getHostEndPointId());
+ Log.d(TAG, registerString + " client with host endpoint ID " + broker.getHostEndPointId());
return IContextHubClient.Stub.asInterface(broker);
}
@@ -203,50 +221,28 @@ import java.util.function.Consumer;
}
/**
- * @param pendingIntent the PendingIntent to check
- * @return true if the given PendingIntent is registered by a client, false otherwise
- */
- /* package */ boolean isPendingIntentRegistered(PendingIntent pendingIntent) {
- for (ContextHubClientBroker broker : mHostEndPointIdToClientMap.values()) {
- if (broker.hasPendingIntent(pendingIntent)) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Creates a new ContextHubClientBroker object for a client and registers it with the client
- * manager.
+ * Returns an available host endpoint ID.
*
- * @param contextHubInfo the object describing the hub this client is attached to
- *
- * @return the ContextHubClientBroker object
+ * @returns an available host endpoint ID
*
* @throws IllegalStateException if max number of clients have already registered
*/
- private synchronized ContextHubClientBroker createNewClientBroker(
- ContextHubInfo contextHubInfo) {
+ private short getHostEndPointId() {
if (mHostEndPointIdToClientMap.size() == MAX_CLIENT_ID + 1) {
throw new IllegalStateException("Could not register client - max limit exceeded");
}
- ContextHubClientBroker broker = null;
- int id = mNextHostEndpointId;
+ int id = mNextHostEndPointId;
for (int i = 0; i <= MAX_CLIENT_ID; i++) {
if (!mHostEndPointIdToClientMap.containsKey((short) id)) {
- broker = new ContextHubClientBroker(
- mContext, mContextHubProxy, this, contextHubInfo, (short) id);
- mHostEndPointIdToClientMap.put((short) id, broker);
- mNextHostEndpointId = (id == MAX_CLIENT_ID) ? 0 : id + 1;
+ mNextHostEndPointId = (id == MAX_CLIENT_ID) ? 0 : id + 1;
break;
}
id = (id == MAX_CLIENT_ID) ? 0 : id + 1;
}
- return broker;
+ return (short) id;
}
/**
@@ -280,9 +276,10 @@ import java.util.function.Consumer;
* @param contextHubId the ID of the Context Hub the client is attached to
* @return the matching ContextHubClientBroker, null if not found
*/
- private ContextHubClientBroker getClientBroker(PendingIntent pendingIntent, int contextHubId) {
+ private ContextHubClientBroker getClientBroker(
+ int contextHubId, PendingIntent pendingIntent, long nanoAppId) {
for (ContextHubClientBroker broker : mHostEndPointIdToClientMap.values()) {
- if (broker.hasPendingIntent(pendingIntent)
+ if (broker.hasPendingIntent(pendingIntent, nanoAppId)
&& broker.getAttachedContextHubId() == contextHubId) {
return broker;
}
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index 215e67c0884f..52f1c6b15f99 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -632,34 +632,26 @@ public class ContextHubService extends IContextHubService.Stub {
}
/**
- * Recreates and binds a IContextHubClientCallback interface to an existing and registered
- * client at the service for the specified Context Hub, provided a previously registered
- * PendingIntent.
+ * Creates and registers a PendingIntent client at the service for the specified Context Hub.
*
- * @param pendingIntent the PendingIntent previously registered for the client
- * @param clientCallback the client interface to register with the service
- * @param contextHubId the ID of the hub this client is attached to
- * @return the generated client interface, null if registration was unsuccessful
+ * @param contextHubId the ID of the hub this client is attached to
+ * @param pendingIntent the PendingIntent associated with this client
+ * @param nanoAppId the ID of the nanoapp PendingIntent events will be sent for
+ * @return the generated client interface
*
- * @throws IllegalArgumentException if contextHubId is not a valid ID
- * @throws NullPointerException if clientCallback or pendingIntent is null
+ * @throws IllegalArgumentException if hubInfo does not represent a valid hub
+ * @throws IllegalStateException if there were too many registered clients at the service
*/
@Override
- public IContextHubClient bindClient(
- PendingIntent pendingIntent, IContextHubClientCallback clientCallback,
- int contextHubId) throws RemoteException {
+ public IContextHubClient createPendingIntentClient(
+ int contextHubId, PendingIntent pendingIntent, long nanoAppId) throws RemoteException {
checkPermissions();
if (!isValidContextHubId(contextHubId)) {
throw new IllegalArgumentException("Invalid context hub ID " + contextHubId);
}
- if (pendingIntent == null) {
- throw new NullPointerException("Cannot create client with null pending intent");
- }
- if (clientCallback == null) {
- throw new NullPointerException("Cannot create client with null callback");
- }
- return mClientManager.bindClient(pendingIntent, clientCallback, contextHubId);
+ ContextHubInfo contextHubInfo = mContextHubIdToInfoMap.get(contextHubId);
+ return mClientManager.registerClient(contextHubInfo, pendingIntent, nanoAppId);
}
/**
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 1c7572ee4e2c..6195ed9e0d79 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -870,6 +870,7 @@ public class NotificationManagerService extends SystemService {
}
if (expanded && userAction) {
r.recordExpanded();
+ reportUserInteraction(r);
}
EventLogTags.writeNotificationExpansion(key,
userAction ? 1 : 0, expanded ? 1 : 0,
@@ -885,6 +886,9 @@ public class NotificationManagerService extends SystemService {
NotificationRecord r = mNotificationsByKey.get(key);
if (r != null) {
r.recordDirectReplied();
+ mMetricsLogger.write(r.getLogMaker()
+ .setCategory(MetricsEvent.NOTIFICATION_DIRECT_REPLY_ACTION)
+ .setType(MetricsEvent.TYPE_ACTION));
reportUserInteraction(r);
}
}
@@ -1160,6 +1164,7 @@ public class NotificationManagerService extends SystemService {
mConditionProviders.onUserSwitched(userId);
mListeners.onUserSwitched(userId);
mZenModeHelper.onUserSwitched(userId);
+ mPreferencesHelper.onUserSwitched(userId);
}
// assistant is the only thing that cares about managed profiles specifically
mAssistants.onUserSwitched(userId);
@@ -1188,6 +1193,7 @@ public class NotificationManagerService extends SystemService {
mConditionProviders.onUserUnlocked(userId);
mListeners.onUserUnlocked(userId);
mZenModeHelper.onUserUnlocked(userId);
+ mPreferencesHelper.onUserUnlocked(userId);
}
}
}
@@ -1982,7 +1988,7 @@ public class NotificationManagerService extends SystemService {
}
/**
- * Report to usage stats that the notification was clicked.
+ * Report to usage stats that the user interacted with the notification.
* @param r notification record
*/
protected void reportUserInteraction(NotificationRecord r) {
@@ -2525,6 +2531,19 @@ public class NotificationManagerService extends SystemService {
}
@Override
+ public int getAppsBypassingDndCount(int userId) {
+ checkCallerIsSystem();
+ return mPreferencesHelper.getAppsBypassingDndCount(userId);
+ }
+
+ @Override
+ public ParceledListSlice<NotificationChannel> getNotificationChannelsBypassingDnd(
+ String pkg, int userId) {
+ checkCallerIsSystem();
+ return mPreferencesHelper.getNotificationChannelsBypassingDnd(pkg, userId);
+ }
+
+ @Override
public boolean areChannelsBypassingDnd() {
return mPreferencesHelper.areChannelsBypassingDnd();
}
@@ -4521,6 +4540,7 @@ public class NotificationManagerService extends SystemService {
mDuration)
.addTaggedData(MetricsEvent.NOTIFICATION_SNOOZED_CRITERIA,
mSnoozeCriterionId == null ? 0 : 1));
+ reportUserInteraction(r);
boolean wasPosted = removeFromNotificationListsLocked(r);
cancelNotificationLocked(r, false, REASON_SNOOZED, wasPosted, null);
updateLightsLocked();
@@ -5529,7 +5549,7 @@ public class NotificationManagerService extends SystemService {
ArrayList<ArrayList<SnoozeCriterion>> snoozeCriteriaBefore = new ArrayList<>(N);
ArrayList<Integer> userSentimentBefore = new ArrayList<>(N);
ArrayList<Integer> suppressVisuallyBefore = new ArrayList<>(N);
- ArrayList<ArrayList<Notification.Action>> smartActionsBefore = new ArrayList<>(N);
+ ArrayList<ArrayList<Notification.Action>> systemSmartActionsBefore = new ArrayList<>(N);
ArrayList<ArrayList<CharSequence>> smartRepliesBefore = new ArrayList<>(N);
for (int i = 0; i < N; i++) {
final NotificationRecord r = mNotificationList.get(i);
@@ -5542,7 +5562,7 @@ public class NotificationManagerService extends SystemService {
snoozeCriteriaBefore.add(r.getSnoozeCriteria());
userSentimentBefore.add(r.getUserSentiment());
suppressVisuallyBefore.add(r.getSuppressedVisualEffects());
- smartActionsBefore.add(r.getSmartActions());
+ systemSmartActionsBefore.add(r.getSystemGeneratedSmartActions());
smartRepliesBefore.add(r.getSmartReplies());
mRankingHelper.extractSignals(r);
}
@@ -5559,7 +5579,8 @@ public class NotificationManagerService extends SystemService {
|| !Objects.equals(userSentimentBefore.get(i), r.getUserSentiment())
|| !Objects.equals(suppressVisuallyBefore.get(i),
r.getSuppressedVisualEffects())
- || !Objects.equals(smartActionsBefore.get(i), r.getSmartActions())
+ || !Objects.equals(systemSmartActionsBefore.get(i),
+ r.getSystemGeneratedSmartActions())
|| !Objects.equals(smartRepliesBefore.get(i), r.getSmartReplies())) {
mHandler.scheduleSendRankingUpdate();
return;
@@ -6561,7 +6582,7 @@ public class NotificationManagerService extends SystemService {
Bundle showBadge = new Bundle();
Bundle userSentiment = new Bundle();
Bundle hidden = new Bundle();
- Bundle smartActions = new Bundle();
+ Bundle systemGeneratedSmartActions = new Bundle();
Bundle smartReplies = new Bundle();
Bundle audiblyAlerted = new Bundle();
Bundle noisy = new Bundle();
@@ -6592,7 +6613,8 @@ public class NotificationManagerService extends SystemService {
showBadge.putBoolean(key, record.canShowBadge());
userSentiment.putInt(key, record.getUserSentiment());
hidden.putBoolean(key, record.isHidden());
- smartActions.putParcelableArrayList(key, record.getSmartActions());
+ systemGeneratedSmartActions.putParcelableArrayList(key,
+ record.getSystemGeneratedSmartActions());
smartReplies.putCharSequenceArrayList(key, record.getSmartReplies());
audiblyAlerted.putBoolean(key, record.getAudiblyAlerted());
noisy.putBoolean(key, record.getSound() != null || record.getVibration() != null);
@@ -6607,7 +6629,7 @@ public class NotificationManagerService extends SystemService {
return new NotificationRankingUpdate(keysAr, interceptedKeysAr, visibilityOverrides,
suppressedVisualEffects, importanceAr, explanation, overrideGroupKeys,
channels, overridePeople, snoozeCriteria, showBadge, userSentiment, hidden,
- smartActions, smartReplies, audiblyAlerted, noisy);
+ systemGeneratedSmartActions, smartReplies, audiblyAlerted, noisy);
}
boolean hasCompanionDevice(ManagedServiceInfo info) {
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index a11b03f68667..1a9257cf17fc 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -163,7 +163,11 @@ public final class NotificationRecord {
private Light mLight;
private String mGroupLogTag;
private String mChannelIdLogTag;
- private ArrayList<Notification.Action> mSmartActions;
+ /**
+ * This list contains system generated smart actions from NAS, app-generated smart actions are
+ * stored in Notification.actions marked as SEMANTIC_ACTION_CONTEXTUAL_SUGGESTION.
+ */
+ private ArrayList<Notification.Action> mSystemGeneratedSmartActions;
private ArrayList<CharSequence> mSmartReplies;
private final List<Adjustment> mAdjustments;
@@ -653,10 +657,11 @@ public final class NotificationRecord {
}
}
if (signals.containsKey(Adjustment.KEY_SMART_ACTIONS)) {
- setSmartActions(signals.getParcelableArrayList(Adjustment.KEY_SMART_ACTIONS));
+ setSystemGeneratedSmartActions(
+ signals.getParcelableArrayList(Adjustment.KEY_SMART_ACTIONS));
MetricsLogger.action(getAdjustmentLogMaker()
.addTaggedData(MetricsEvent.ADJUSTMENT_KEY_SMART_ACTIONS,
- getSmartActions().size()));
+ getSystemGeneratedSmartActions().size()));
}
if (signals.containsKey(Adjustment.KEY_SMART_REPLIES)) {
setSmartReplies(signals.getCharSequenceArrayList(Adjustment.KEY_SMART_REPLIES));
@@ -1132,12 +1137,13 @@ public final class NotificationRecord {
mHasSeenSmartReplies = hasSeenSmartReplies;
}
- public void setSmartActions(ArrayList<Notification.Action> smartActions) {
- mSmartActions = smartActions;
+ public void setSystemGeneratedSmartActions(
+ ArrayList<Notification.Action> systemGeneratedSmartActions) {
+ mSystemGeneratedSmartActions = systemGeneratedSmartActions;
}
- public ArrayList<Notification.Action> getSmartActions() {
- return mSmartActions;
+ public ArrayList<Notification.Action> getSystemGeneratedSmartActions() {
+ return mSystemGeneratedSmartActions;
}
public void setSmartReplies(ArrayList<CharSequence> smartReplies) {
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 8fce5e3acdc2..fd65ebe102ac 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -111,7 +111,6 @@ public class PreferencesHelper implements RankingConfig {
// pkg => PackagePreferences
private final ArrayMap<String, PackagePreferences> mRestoredWithoutUids = new ArrayMap<>();
-
private final Context mContext;
private final PackageManager mPm;
private final RankingHandler mRankingHandler;
@@ -120,7 +119,6 @@ public class PreferencesHelper implements RankingConfig {
private SparseBooleanArray mBadgingEnabled;
private boolean mAreChannelsBypassingDnd;
-
public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
ZenModeHelper zenHelper) {
mContext = context;
@@ -129,11 +127,7 @@ public class PreferencesHelper implements RankingConfig {
mPm = pm;
updateBadgingEnabled();
-
- mAreChannelsBypassingDnd = (mZenModeHelper.getNotificationPolicy().state &
- NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND) == 1;
- updateChannelsBypassingDnd();
-
+ syncChannelsBypassingDnd(mContext.getUserId());
}
public void readXml(XmlPullParser parser, boolean forRestore)
@@ -525,6 +519,7 @@ public class PreferencesHelper implements RankingConfig {
// but the system can
if (group.isBlocked() != oldGroup.isBlocked()) {
group.lockFields(NotificationChannelGroup.USER_LOCKED_BLOCKED_STATE);
+ updateChannelsBypassingDnd(mContext.getUserId());
}
if (group.canOverlayApps() != oldGroup.canOverlayApps()) {
group.lockFields(NotificationChannelGroup.USER_LOCKED_ALLOW_APP_OVERLAY);
@@ -571,6 +566,7 @@ public class PreferencesHelper implements RankingConfig {
// Apps are allowed to downgrade channel importance if the user has not changed any
// fields on this channel yet.
+ final int previousExistingImportance = existing.getImportance();
if (existing.getUserLockedFields() == 0 &&
channel.getImportance() < existing.getImportance()) {
existing.setImportance(channel.getImportance());
@@ -582,8 +578,9 @@ public class PreferencesHelper implements RankingConfig {
boolean bypassDnd = channel.canBypassDnd();
existing.setBypassDnd(bypassDnd);
- if (bypassDnd != mAreChannelsBypassingDnd) {
- updateChannelsBypassingDnd();
+ if (bypassDnd != mAreChannelsBypassingDnd
+ || previousExistingImportance != existing.getImportance()) {
+ updateChannelsBypassingDnd(mContext.getUserId());
}
}
@@ -613,7 +610,7 @@ public class PreferencesHelper implements RankingConfig {
r.channels.put(channel.getId(), channel);
if (channel.canBypassDnd() != mAreChannelsBypassingDnd) {
- updateChannelsBypassingDnd();
+ updateChannelsBypassingDnd(mContext.getUserId());
}
MetricsLogger.action(getChannelLog(channel, pkg).setType(
com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_OPEN));
@@ -663,8 +660,9 @@ public class PreferencesHelper implements RankingConfig {
MetricsLogger.action(getChannelLog(updatedChannel, pkg));
}
- if (updatedChannel.canBypassDnd() != mAreChannelsBypassingDnd) {
- updateChannelsBypassingDnd();
+ if (updatedChannel.canBypassDnd() != mAreChannelsBypassingDnd
+ || channel.getImportance() != updatedChannel.getImportance()) {
+ updateChannelsBypassingDnd(mContext.getUserId());
}
updateConfig();
}
@@ -701,7 +699,7 @@ public class PreferencesHelper implements RankingConfig {
MetricsLogger.action(lm);
if (mAreChannelsBypassingDnd && channel.canBypassDnd()) {
- updateChannelsBypassingDnd();
+ updateChannelsBypassingDnd(mContext.getUserId());
}
}
}
@@ -859,6 +857,27 @@ public class PreferencesHelper implements RankingConfig {
}
/**
+ * Gets all notification channels associated with the given pkg and userId that can bypass dnd
+ */
+ public ParceledListSlice<NotificationChannel> getNotificationChannelsBypassingDnd(String pkg,
+ int userId) {
+ List<NotificationChannel> channels = new ArrayList<>();
+ synchronized (mPackagePreferences) {
+ final PackagePreferences r = mPackagePreferences.get(
+ packagePreferencesKey(pkg, userId));
+ // notifications from this package aren't blocked
+ if (r != null && r.importance != IMPORTANCE_NONE) {
+ for (NotificationChannel channel : r.channels.values()) {
+ if (channelIsLive(r, channel) && channel.canBypassDnd()) {
+ channels.add(channel);
+ }
+ }
+ }
+ }
+ return new ParceledListSlice<>(channels);
+ }
+
+ /**
* True for pre-O apps that only have the default channel, or pre O apps that have no
* channels yet. This method will create the default channel for pre-O apps that don't have it.
* Should never be true for O+ targeting apps, but that's enforced on boot/when an app
@@ -922,18 +941,62 @@ public class PreferencesHelper implements RankingConfig {
return count;
}
- public void updateChannelsBypassingDnd() {
+ /**
+ * Returns the number of apps that have at least one notification channel that can bypass DND
+ * for given particular user
+ */
+ public int getAppsBypassingDndCount(int userId) {
+ int count = 0;
+ synchronized (mPackagePreferences) {
+ final int numPackagePreferences = mPackagePreferences.size();
+ for (int i = 0; i < numPackagePreferences; i++) {
+ final PackagePreferences r = mPackagePreferences.valueAt(i);
+ // Package isn't associated with this userId or notifications from this package are
+ // blocked
+ if (userId != UserHandle.getUserId(r.uid) || r.importance == IMPORTANCE_NONE) {
+ continue;
+ }
+
+ for (NotificationChannel channel : r.channels.values()) {
+ if (channelIsLive(r, channel) && channel.canBypassDnd()) {
+ count++;
+ break;
+ }
+ }
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Syncs {@link #mAreChannelsBypassingDnd} with the user's notification policy before
+ * updating
+ * @param userId
+ */
+ private void syncChannelsBypassingDnd(int userId) {
+ mAreChannelsBypassingDnd = (mZenModeHelper.getNotificationPolicy().state
+ & NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND) == 1;
+ updateChannelsBypassingDnd(userId);
+ }
+
+ /**
+ * Updates the user's NotificationPolicy based on whether the given userId
+ * has channels bypassing DND
+ * @param userId
+ */
+ private void updateChannelsBypassingDnd(int userId) {
synchronized (mPackagePreferences) {
- final int numPackagePreferencess = mPackagePreferences.size();
- for (int PackagePreferencesIndex = 0; PackagePreferencesIndex < numPackagePreferencess;
- PackagePreferencesIndex++) {
- final PackagePreferences r = mPackagePreferences.valueAt(PackagePreferencesIndex);
- final int numChannels = r.channels.size();
-
- for (int channelIndex = 0; channelIndex < numChannels; channelIndex++) {
- NotificationChannel channel = r.channels.valueAt(channelIndex);
- if (!channel.isDeleted() && channel.canBypassDnd()) {
- // If any channel bypasses DND, synchronize state and return early.
+ final int numPackagePreferences = mPackagePreferences.size();
+ for (int i = 0; i < numPackagePreferences; i++) {
+ final PackagePreferences r = mPackagePreferences.valueAt(i);
+ // Package isn't associated with this userId or notifications from this package are
+ // blocked
+ if (userId != UserHandle.getUserId(r.uid) || r.importance == IMPORTANCE_NONE) {
+ continue;
+ }
+
+ for (NotificationChannel channel : r.channels.values()) {
+ if (channelIsLive(r, channel) && channel.canBypassDnd()) {
if (!mAreChannelsBypassingDnd) {
mAreChannelsBypassingDnd = true;
updateZenPolicy(true);
@@ -943,7 +1006,6 @@ public class PreferencesHelper implements RankingConfig {
}
}
}
-
// If no channels bypass DND, update the zen policy once to disable DND bypass.
if (mAreChannelsBypassingDnd) {
mAreChannelsBypassingDnd = false;
@@ -951,6 +1013,22 @@ public class PreferencesHelper implements RankingConfig {
}
}
+ private boolean channelIsLive(PackagePreferences pkgPref, NotificationChannel channel) {
+ // Channel is in a group that's blocked
+ if (!TextUtils.isEmpty(channel.getGroup())) {
+ if (pkgPref.groups.get(channel.getGroup()).isBlocked()) {
+ return false;
+ }
+ }
+
+ // Channel is deleted or is blocked
+ if (channel.isDeleted() || channel.getImportance() == IMPORTANCE_NONE) {
+ return false;
+ }
+
+ return true;
+ }
+
public void updateZenPolicy(boolean areChannelsBypassingDnd) {
NotificationManager.Policy policy = mZenModeHelper.getNotificationPolicy();
mZenModeHelper.setNotificationPolicy(new NotificationManager.Policy(
@@ -1329,6 +1407,20 @@ public class PreferencesHelper implements RankingConfig {
return packageChannels;
}
+ /**
+ * Called when user switches
+ */
+ public void onUserSwitched(int userId) {
+ syncChannelsBypassingDnd(userId);
+ }
+
+ /**
+ * Called when user is unlocked
+ */
+ public void onUserUnlocked(int userId) {
+ syncChannelsBypassingDnd(userId);
+ }
+
public void onUserRemoved(int userId) {
synchronized (mPackagePreferences) {
int N = mPackagePreferences.size();
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
index 807c343d0d10..731e6bcfb074 100644
--- a/services/core/java/com/android/server/om/IdmapManager.java
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -16,36 +16,46 @@
package com.android.server.om;
+import static android.content.Context.IDMAP_SERVICE;
+import static android.text.format.DateUtils.SECOND_IN_MILLIS;
+
import static com.android.server.om.OverlayManagerService.DEBUG;
import static com.android.server.om.OverlayManagerService.TAG;
import android.annotation.NonNull;
import android.content.om.OverlayInfo;
import android.content.pm.PackageInfo;
+import android.os.IBinder;
+import android.os.IIdmap2;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.Slog;
-import com.android.server.pm.Installer.InstallerException;
+import com.android.internal.os.BackgroundThread;
import com.android.server.pm.Installer;
-import java.io.DataInputStream;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
/**
* Handle the creation and deletion of idmap files.
*
* The actual work is performed by the idmap binary, launched through Installer
- * and installd.
+ * and installd (or idmap2).
*
* Note: this class is subclassed in the OMS unit tests, and hence not marked as final.
*/
class IdmapManager {
+ private static final boolean FEATURE_FLAG_IDMAP2 = false;
+
private final Installer mInstaller;
+ private IIdmap2 mIdmap2Service;
IdmapManager(final Installer installer) {
mInstaller = installer;
+ if (FEATURE_FLAG_IDMAP2) {
+ connectToIdmap2d();
+ }
}
boolean createIdmap(@NonNull final PackageInfo targetPackage,
@@ -59,8 +69,12 @@ class IdmapManager {
final String targetPath = targetPackage.applicationInfo.getBaseCodePath();
final String overlayPath = overlayPackage.applicationInfo.getBaseCodePath();
try {
- mInstaller.idmap(targetPath, overlayPath, sharedGid);
- } catch (InstallerException e) {
+ if (FEATURE_FLAG_IDMAP2) {
+ mIdmap2Service.createIdmap(targetPath, overlayPath, userId);
+ } else {
+ mInstaller.idmap(targetPath, overlayPath, sharedGid);
+ }
+ } catch (Exception e) {
Slog.w(TAG, "failed to generate idmap for " + targetPath + " and "
+ overlayPath + ": " + e.getMessage());
return false;
@@ -69,13 +83,16 @@ class IdmapManager {
}
boolean removeIdmap(@NonNull final OverlayInfo oi, final int userId) {
- // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
if (DEBUG) {
Slog.d(TAG, "remove idmap for " + oi.baseCodePath);
}
try {
- mInstaller.removeIdmap(oi.baseCodePath);
- } catch (InstallerException e) {
+ if (FEATURE_FLAG_IDMAP2) {
+ mIdmap2Service.removeIdmap(oi.baseCodePath, userId);
+ } else {
+ mInstaller.removeIdmap(oi.baseCodePath);
+ }
+ } catch (Exception e) {
Slog.w(TAG, "failed to remove idmap for " + oi.baseCodePath + ": " + e.getMessage());
return false;
}
@@ -83,19 +100,58 @@ class IdmapManager {
}
boolean idmapExists(@NonNull final OverlayInfo oi) {
- // unused OverlayInfo.userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
- return new File(getIdmapPath(oi.baseCodePath)).isFile();
+ return new File(getIdmapPath(oi.baseCodePath, oi.userId)).isFile();
}
boolean idmapExists(@NonNull final PackageInfo overlayPackage, final int userId) {
- // unused userId: see comment in OverlayManagerServiceImpl.removeIdmapIfPossible
- return new File(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath())).isFile();
+ return new File(getIdmapPath(overlayPackage.applicationInfo.getBaseCodePath(), userId))
+ .isFile();
}
- private String getIdmapPath(@NonNull final String baseCodePath) {
- final StringBuilder sb = new StringBuilder("/data/resource-cache/");
- sb.append(baseCodePath.substring(1).replace('/', '@'));
- sb.append("@idmap");
- return sb.toString();
+ private @NonNull String getIdmapPath(@NonNull final String overlayPackagePath,
+ final int userId) {
+ if (FEATURE_FLAG_IDMAP2) {
+ try {
+ return mIdmap2Service.getIdmapPath(overlayPackagePath, userId);
+ } catch (Exception e) {
+ Slog.w(TAG, "failed to get idmap path for " + overlayPackagePath + ": "
+ + e.getMessage());
+ return "";
+ }
+ } else {
+ final StringBuilder sb = new StringBuilder("/data/resource-cache/");
+ sb.append(overlayPackagePath.substring(1).replace('/', '@'));
+ sb.append("@idmap");
+ return sb.toString();
+ }
+ }
+
+ private void connectToIdmap2d() {
+ IBinder binder = ServiceManager.getService(IDMAP_SERVICE);
+ if (binder != null) {
+ try {
+ binder.linkToDeath(new IBinder.DeathRecipient() {
+ @Override
+ public void binderDied() {
+ Slog.w(TAG, "service '" + IDMAP_SERVICE + "' died; reconnecting...");
+ connectToIdmap2d();
+ }
+
+ }, 0);
+ } catch (RemoteException e) {
+ binder = null;
+ }
+ }
+ if (binder != null) {
+ mIdmap2Service = IIdmap2.Stub.asInterface(binder);
+ if (DEBUG) {
+ Slog.d(TAG, "service '" + IDMAP_SERVICE + "' connected");
+ }
+ } else {
+ Slog.w(TAG, "service '" + IDMAP_SERVICE + "' not found; trying again...");
+ BackgroundThread.getHandler().postDelayed(() -> {
+ connectToIdmap2d();
+ }, SECOND_IN_MILLIS);
+ }
}
}
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index 36bf83dfe92c..572d36897040 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -179,19 +179,13 @@ final class OverlayManagerSettings {
List<OverlayInfo> getOverlaysForTarget(@NonNull final String targetPackageName,
final int userId) {
- // Static RROs targeting "android" are loaded from AssetManager, and so they should be
- // ignored in OverlayManagerService.
return selectWhereTarget(targetPackageName, userId)
- .filter((i) -> !(i.isStatic() && "android".equals(i.getTargetPackageName())))
.map(SettingsItem::getOverlayInfo)
.collect(Collectors.toList());
}
ArrayMap<String, List<OverlayInfo>> getOverlaysForUser(final int userId) {
- // Static RROs targeting "android" are loaded from AssetManager, and so they should be
- // ignored in OverlayManagerService.
return selectWhereUser(userId)
- .filter((i) -> !(i.isStatic() && "android".equals(i.getTargetPackageName())))
.map(SettingsItem::getOverlayInfo)
.collect(Collectors.groupingBy(info -> info.targetPackageName, ArrayMap::new,
Collectors.toList()));
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 275f3dcdb6d2..b4903817f787 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -362,7 +362,7 @@ public class LauncherAppsService extends SystemService {
}
private static boolean shouldShowHiddenApp(ApplicationInfo appInfo) {
- if (appInfo.isSystemApp() || appInfo.isUpdatedSystemApp()) {
+ if (appInfo == null || appInfo.isSystemApp() || appInfo.isUpdatedSystemApp()) {
return false;
}
return true;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 8a0c416ece04..e4e8010ac9e9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -12937,6 +12937,25 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
+ @Override
+ public boolean canSuspendPackageForUser(String packageName, int userId) {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.SUSPEND_APPS,
+ "canSuspendPackageForUser");
+ final int callingUid = Binder.getCallingUid();
+ if (UserHandle.getUserId(callingUid) != userId) {
+ throw new SecurityException("Calling uid " + callingUid
+ + " cannot query canSuspendPackageForUser for user " + userId);
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mPackages) {
+ return canSuspendPackageForUserLocked(packageName, userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
@GuardedBy("mPackages")
private boolean canSuspendPackageForUserLocked(String packageName, int userId) {
if (isPackageDeviceAdmin(packageName, userId)) {
@@ -13000,7 +13019,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
if (PLATFORM_PACKAGE_NAME.equals(packageName)) {
- Slog.w(TAG, "Cannot suspend package: " + packageName);
+ Slog.w(TAG, "Cannot suspend the platform package: " + packageName);
return false;
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 4c93441b5c7b..6009bd3e2c82 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2637,7 +2637,7 @@ public final class Settings {
}
for (final SharedUserSetting sus : mSharedUsers.values()) {
- knownSet.remove(sus.getSandboxName());
+ knownSet.remove(sus.getStorageSandboxName());
}
// Remove any unclaimed mappings
@@ -2653,7 +2653,8 @@ public final class Settings {
void writeKernelMappingLPr(SharedUserSetting sus) {
if (mKernelMappingFilename == null || sus == null || sus.name == null) return;
- writeKernelMappingLPr(sus.getSandboxName(), sus.userId, sus.getNotInstalledUserIds());
+ writeKernelMappingLPr(sus.getStorageSandboxName(),
+ sus.userId, sus.getNotInstalledUserIds());
}
void writeKernelMappingLPr(PackageSetting ps) {
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index 32826e51f0a4..d67144e8ce39 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -19,6 +19,7 @@ package com.android.server.pm;
import android.annotation.Nullable;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageParser;
+import android.os.storage.StorageManager;
import android.service.pm.PackageServiceDumpProto;
import android.util.ArraySet;
import android.util.proto.ProtoOutputStream;
@@ -166,8 +167,8 @@ public final class SharedUserSetting extends SettingBase {
return excludedUserIds == null ? EmptyArray.INT : excludedUserIds;
}
- public String getSandboxName() {
- return "shared:" + name;
+ public String getStorageSandboxName() {
+ return StorageManager.SHARED_SANDBOX_PREFIX + name;
}
/** Updates all fields in this shared user setting from another. */
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index a55b49fe028d..f78d2639df1a 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -20,7 +20,7 @@ import android.app.ActivityManager;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.security.IKeystoreService;
+import android.security.keystore.IKeystoreService;
import android.util.Slog;
import com.android.internal.policy.IKeyguardService;
diff --git a/services/core/java/com/android/server/role/RemoteRoleControllerService.java b/services/core/java/com/android/server/role/RemoteRoleControllerService.java
index b670291ba94b..7d34270734df 100644
--- a/services/core/java/com/android/server/role/RemoteRoleControllerService.java
+++ b/services/core/java/com/android/server/role/RemoteRoleControllerService.java
@@ -16,10 +16,10 @@
package com.android.server.role;
-import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.annotation.WorkerThread;
import android.app.role.IRoleManagerCallback;
import android.app.role.RoleManagerCallback;
import android.content.ComponentName;
@@ -34,6 +34,7 @@ import android.rolecontrollerservice.IRoleControllerService;
import android.rolecontrollerservice.RoleControllerService;
import android.util.Slog;
+import com.android.internal.os.BackgroundThread;
import com.android.internal.util.function.pooled.PooledLambda;
import java.util.ArrayDeque;
@@ -44,9 +45,13 @@ import java.util.Queue;
*/
public class RemoteRoleControllerService {
+ static final boolean DEBUG = false;
private static final String LOG_TAG = RemoteRoleControllerService.class.getSimpleName();
@NonNull
+ private static final Handler sCallbackHandler = BackgroundThread.getHandler();
+
+ @NonNull
private final Connection mConnection;
public RemoteRoleControllerService(@UserIdInt int userId, @NonNull Context context) {
@@ -87,6 +92,16 @@ public class RemoteRoleControllerService {
service.onClearRoleHolders(roleName, callbackDelegate), callback));
}
+ /**
+ * Performs granting of default roles and permissions and appops
+ *
+ * @see RoleControllerService#onGrantDefaultRoles(RoleManagerCallback)
+ */
+ public void onGrantDefaultRoles(@NonNull IRoleManagerCallback callback) {
+ mConnection.enqueueCall(
+ new Connection.Call(IRoleControllerService::onGrantDefaultRoles, callback));
+ }
+
private static final class Connection implements ServiceConnection {
private static final long UNBIND_DELAY_MILLIS = 15 * 1000;
@@ -106,9 +121,6 @@ public class RemoteRoleControllerService {
private final Queue<Call> mPendingCalls = new ArrayDeque<>();
@NonNull
- private final Handler mMainHandler = Handler.getMain();
-
- @NonNull
private final Runnable mUnbindRunnable = this::unbind;
Connection(@UserIdInt int userId, @NonNull Context context) {
@@ -116,14 +128,14 @@ public class RemoteRoleControllerService {
mContext = context;
}
- @MainThread
@Override
+ @WorkerThread
public void onServiceConnected(@NonNull ComponentName name, @NonNull IBinder service) {
mService = IRoleControllerService.Stub.asInterface(service);
executePendingCalls();
}
- @MainThread
+ @WorkerThread
private void executePendingCalls() {
while (!mPendingCalls.isEmpty()) {
Call call = mPendingCalls.poll();
@@ -132,26 +144,33 @@ public class RemoteRoleControllerService {
scheduleUnbind();
}
- @MainThread
@Override
+ @WorkerThread
public void onServiceDisconnected(@NonNull ComponentName name) {
mService = null;
}
- @MainThread
@Override
+ @WorkerThread
public void onBindingDied(@NonNull ComponentName name) {
unbind();
}
public void enqueueCall(@NonNull Call call) {
- mMainHandler.post(PooledLambda.obtainRunnable(this::executeCall, call));
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "Enqueue " + call);
+ }
+ sCallbackHandler.executeOrSendMessage(PooledLambda.obtainMessage(
+ Connection::executeCall, this, call));
}
- @MainThread
+ @WorkerThread
private void executeCall(@NonNull Call call) {
ensureBound();
if (mService == null) {
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "Delaying until service connected: " + call);
+ }
mPendingCalls.offer(call);
return;
}
@@ -159,24 +178,28 @@ public class RemoteRoleControllerService {
scheduleUnbind();
}
- @MainThread
+ @WorkerThread
private void ensureBound() {
- mMainHandler.removeCallbacks(mUnbindRunnable);
+ sCallbackHandler.removeCallbacks(mUnbindRunnable);
if (!mBound) {
Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
intent.setPackage(mContext.getPackageManager()
.getPermissionControllerPackageName());
+ // Use direct handler to ensure onServiceConnected callback happens in the same
+ // call frame, as required by onGrantDefaultRoles
+ //
+ // Note that as a result, onServiceConnected may happen not on main thread!
mBound = mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE,
- UserHandle.of(mUserId));
+ sCallbackHandler, UserHandle.of(mUserId));
}
}
private void scheduleUnbind() {
- mMainHandler.removeCallbacks(mUnbindRunnable);
- mMainHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS);
+ sCallbackHandler.removeCallbacks(mUnbindRunnable);
+ sCallbackHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS);
}
- @MainThread
+ @WorkerThread
private void unbind() {
if (mBound) {
mService = null;
@@ -196,9 +219,6 @@ public class RemoteRoleControllerService {
private final IRoleManagerCallback mCallback;
@NonNull
- private final Handler mMainHandler = Handler.getMain();
-
- @NonNull
private final Runnable mTimeoutRunnable = () -> notifyCallback(false);
private boolean mCallbackNotified;
@@ -209,10 +229,13 @@ public class RemoteRoleControllerService {
mCallback = callback;
}
- @MainThread
+ @WorkerThread
public void execute(IRoleControllerService service) {
+ if (DEBUG) {
+ Slog.i(LOG_TAG, "Executing " + this);
+ }
try {
- mMainHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MILLIS);
+ sCallbackHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MILLIS);
mCallExecutor.execute(service, new CallbackDelegate());
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Error calling RoleControllerService", e);
@@ -220,13 +243,13 @@ public class RemoteRoleControllerService {
}
}
- @MainThread
+ @WorkerThread
private void notifyCallback(boolean success) {
if (mCallbackNotified) {
return;
}
mCallbackNotified = true;
- mMainHandler.removeCallbacks(mTimeoutRunnable);
+ sCallbackHandler.removeCallbacks(mTimeoutRunnable);
try {
if (success) {
mCallback.onSuccess();
@@ -239,10 +262,15 @@ public class RemoteRoleControllerService {
}
}
+ @Override
+ public String toString() {
+ return "Call with callback: " + mCallback;
+ }
+
@FunctionalInterface
public interface CallExecutor {
- @MainThread
+ @WorkerThread
void execute(IRoleControllerService service, IRoleManagerCallback callbackDelegate)
throws RemoteException;
}
@@ -251,13 +279,14 @@ public class RemoteRoleControllerService {
@Override
public void onSuccess() throws RemoteException {
- mMainHandler.post(PooledLambda.obtainRunnable(Call.this::notifyCallback, true));
+ sCallbackHandler.sendMessage(PooledLambda.obtainMessage(
+ Call::notifyCallback, Call.this, true));
}
@Override
public void onFailure() throws RemoteException {
- mMainHandler.post(PooledLambda.obtainRunnable(Call.this::notifyCallback,
- false));
+ sCallbackHandler.sendMessage(PooledLambda.obtainMessage(
+ Call::notifyCallback, Call.this, false));
}
}
}
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index ded075d5742c..d01e7621dd39 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -45,6 +45,10 @@ import com.android.server.SystemService;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* Service for role management.
@@ -105,17 +109,37 @@ public class RoleManagerService extends SystemService {
public void onStart() {
publishBinderService(Context.ROLE_SERVICE, new Stub());
//TODO add watch for new user creation and run default grants for them
+ //TODO add package update watch to detect PermissionController upgrade and run def. grants
}
@Override
public void onStartUser(@UserIdInt int userId) {
synchronized (mLock) {
//TODO only call into PermissionController if it or system upgreaded (for boot time)
- // (add package changes watch;
- // we can detect upgrade using build fingerprint and app version)
getUserStateLocked(userId);
- //TODO call permission grant policy here
+ }
+ //TODO consider calling grants only when certain conditions are met
+ // such as OS or PermissionController upgrade
+ if (RemoteRoleControllerService.DEBUG) {
Slog.i(LOG_TAG, "Granting default permissions...");
+ CompletableFuture<Void> result = new CompletableFuture<>();
+ getControllerService(userId).onGrantDefaultRoles(
+ new IRoleManagerCallback.Stub() {
+ @Override
+ public void onSuccess() {
+ result.complete(null);
+ }
+
+ @Override
+ public void onFailure() {
+ result.completeExceptionally(new RuntimeException());
+ }
+ });
+ try {
+ result.get(5, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ Slog.e(LOG_TAG, "Failed to grant defaults for user " + userId, e);
+ }
}
}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index cef484f07972..3050409e67f9 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -41,9 +41,13 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.hardware.fingerprint.FingerprintManager;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkRequest;
import android.net.NetworkStats;
import android.net.wifi.IWifiManager;
import android.net.wifi.WifiActivityEnergyInfo;
+import android.os.BatteryStats;
import android.os.BatteryStatsInternal;
import android.os.Binder;
import android.os.Bundle;
@@ -84,6 +88,8 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.procstats.IProcessStats;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.net.NetworkStatsFactory;
+import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.os.BinderCallsStats.ExportedCallStat;
import com.android.internal.os.KernelCpuSpeedReader;
import com.android.internal.os.KernelCpuThreadReader;
@@ -202,6 +208,10 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
@Nullable
private final KernelCpuThreadReader mKernelCpuThreadReader;
+ private BatteryStatsHelper mBatteryStatsHelper = null;
+ private static final int MAX_BATTERY_STATS_HELPER_FREQUENCY_MS = 1000;
+ private long mBatteryStatsHelperTimestampMs = -MAX_BATTERY_STATS_HELPER_FREQUENCY_MS;
+
private static IThermalService sThermalService;
private File mBaseDir =
new File(SystemServiceManager.ensureSystemDir(), "stats_companion");
@@ -271,6 +281,12 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
Slog.e(TAG, "cannot find thermalservice, no throttling push notifications");
}
+ // Default NetworkRequest should cover all transport types.
+ final NetworkRequest request = new NetworkRequest.Builder().build();
+ final ConnectivityManager connectivityManager =
+ (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ connectivityManager.registerNetworkCallback(request, new ConnectivityStatsCallback());
+
HandlerThread handlerThread = new HandlerThread(TAG);
handlerThread.start();
mHandler = new CompanionHandler(handlerThread.getLooper());
@@ -357,6 +373,8 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
List<Integer> uids = new ArrayList<>();
List<Long> versions = new ArrayList<>();
List<String> apps = new ArrayList<>();
+ List<String> versionStrings = new ArrayList<>();
+ List<String> installers = new ArrayList<>();
// Add in all the apps for every user/profile.
for (UserInfo profile : users) {
@@ -364,14 +382,24 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
pm.getInstalledPackagesAsUser(PackageManager.MATCH_KNOWN_PACKAGES, profile.id);
for (int j = 0; j < pi.size(); j++) {
if (pi.get(j).applicationInfo != null) {
+ String installer;
+ try {
+ installer = pm.getInstallerPackageName(pi.get(j).packageName);
+ } catch (IllegalArgumentException e) {
+ installer = "";
+ }
+ installers.add(installer == null ? "" : installer);
uids.add(pi.get(j).applicationInfo.uid);
versions.add(pi.get(j).getLongVersionCode());
+ versionStrings.add(pi.get(j).versionName);
apps.add(pi.get(j).packageName);
}
}
}
- sStatsd.informAllUidData(toIntArray(uids), toLongArray(versions), apps.toArray(new
- String[apps.size()]));
+ sStatsd.informAllUidData(toIntArray(uids), toLongArray(versions),
+ versionStrings.toArray(new String[versionStrings.size()]),
+ apps.toArray(new String[apps.size()]),
+ installers.toArray(new String[installers.size()]));
if (DEBUG) {
Slog.d(TAG, "Sent data for " + uids.size() + " apps");
}
@@ -413,7 +441,14 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
int uid = b.getInt(Intent.EXTRA_UID);
String app = intent.getData().getSchemeSpecificPart();
PackageInfo pi = pm.getPackageInfo(app, PackageManager.MATCH_ANY_USER);
- sStatsd.informOnePackage(app, uid, pi.getLongVersionCode());
+ String installer;
+ try {
+ installer = pm.getInstallerPackageName(app);
+ } catch (IllegalArgumentException e) {
+ installer = "";
+ }
+ sStatsd.informOnePackage(app, uid, pi.getLongVersionCode(), pi.versionName,
+ installer == null ? "" : installer);
}
} catch (Exception e) {
Slog.w(TAG, "Failed to inform statsd of an app update", e);
@@ -1421,6 +1456,73 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
pulledData.add(e);
}
+ private BatteryStatsHelper getBatteryStatsHelper() {
+ if (mBatteryStatsHelper == null) {
+ final long callingToken = Binder.clearCallingIdentity();
+ try {
+ // clearCallingIdentity required for BatteryStatsHelper.checkWifiOnly().
+ mBatteryStatsHelper = new BatteryStatsHelper(mContext, false);
+ } finally {
+ Binder.restoreCallingIdentity(callingToken);
+ }
+ mBatteryStatsHelper.create((Bundle) null);
+ }
+ long currentTime = SystemClock.elapsedRealtime();
+ if (currentTime - mBatteryStatsHelperTimestampMs >= MAX_BATTERY_STATS_HELPER_FREQUENCY_MS) {
+ // Load BatteryStats and do all the calculations.
+ mBatteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.USER_ALL);
+ // Calculations are done so we don't need to save the raw BatteryStats data in RAM.
+ mBatteryStatsHelper.clearStats();
+ mBatteryStatsHelperTimestampMs = currentTime;
+ }
+ return mBatteryStatsHelper;
+ }
+
+ private void pullDeviceCalculatedPowerUse(int tagId,
+ long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
+ BatteryStatsHelper bsHelper = getBatteryStatsHelper();
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
+ e.writeFloat((float) bsHelper.getComputedPower());
+ pulledData.add(e);
+ }
+
+ private void pullDeviceCalculatedPowerBlameUid(int tagId,
+ long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
+ final List<BatterySipper> sippers = getBatteryStatsHelper().getUsageList();
+ if (sippers == null) {
+ return;
+ }
+ for (BatterySipper bs : sippers) {
+ if (bs.drainType != bs.drainType.APP) {
+ continue;
+ }
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
+ e.writeInt(bs.uidObj.getUid());
+ e.writeFloat((float) bs.totalPowerMah);
+ pulledData.add(e);
+ }
+ }
+
+ private void pullDeviceCalculatedPowerBlameOther(int tagId,
+ long elapsedNanos, final long wallClockNanos, List<StatsLogEventWrapper> pulledData) {
+ final List<BatterySipper> sippers = getBatteryStatsHelper().getUsageList();
+ if (sippers == null) {
+ return;
+ }
+ for (BatterySipper bs : sippers) {
+ if (bs.drainType == bs.drainType.APP) {
+ continue; // This is a separate atom; see pullDeviceCalculatedPowerBlameUid().
+ }
+ if (bs.drainType == bs.drainType.USER) {
+ continue; // This is not supported. We purposefully calculate over USER_ALL.
+ }
+ StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
+ e.writeInt(bs.drainType.ordinal());
+ e.writeFloat((float) bs.totalPowerMah);
+ pulledData.add(e);
+ }
+ }
+
private void pullDiskIo(int tagId, long elapsedNanos, final long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
mStoragedUidIoStatsReader.readAbsolute((uid, fgCharsRead, fgCharsWrite, fgBytesRead,
@@ -1646,6 +1748,18 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
pullCpuTimePerThreadFreq(tagId, elapsedNanos, wallClockNanos, ret);
break;
}
+ case StatsLog.DEVICE_CALCULATED_POWER_USE: {
+ pullDeviceCalculatedPowerUse(tagId, elapsedNanos, wallClockNanos, ret);
+ break;
+ }
+ case StatsLog.DEVICE_CALCULATED_POWER_BLAME_UID: {
+ pullDeviceCalculatedPowerBlameUid(tagId, elapsedNanos, wallClockNanos, ret);
+ break;
+ }
+ case StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER: {
+ pullDeviceCalculatedPowerBlameOther(tagId, elapsedNanos, wallClockNanos, ret);
+ break;
+ }
default:
Slog.w(TAG, "No such tagId data as " + tagId);
return null;
@@ -1875,4 +1989,19 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
temp.getValue());
}
}
+
+ private static final class ConnectivityStatsCallback extends
+ ConnectivityManager.NetworkCallback {
+ @Override
+ public void onAvailable(Network network) {
+ StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId,
+ StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__CONNECTED);
+ }
+
+ @Override
+ public void onLost(Network network) {
+ StatsLog.write(StatsLog.CONNECTIVITY_STATE_CHANGED, network.netId,
+ StatsLog.CONNECTIVITY_STATE_CHANGED__STATE__DISCONNECTED);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 10121c43e335..3e07ebea6a17 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -37,6 +37,7 @@ import android.os.UserHandle;
import android.service.notification.NotificationStats;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.Log;
import android.util.Slog;
import com.android.internal.R;
@@ -671,6 +672,20 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
// Ensure state for the current user is applied, even if passed a non-current user.
final int net1 = gatherDisableActionsLocked(mCurrentUserId, 1);
final int net2 = gatherDisableActionsLocked(mCurrentUserId, 2);
+
+ // TODO(b/113914868): investigation log for disappearing home button
+ if (whichFlag == 1 && pkg.contains("systemui")) {
+ String disabledData = "{ ";
+ for (int i = 0; i < mDisableRecords.size(); i++) {
+ DisableRecord tok = mDisableRecords.get(i);
+ disabledData += " ([" + i + "] " + tok + "), ";
+ }
+ disabledData += " }";
+ Log.d(TAG, "disabledlocked (b/113914868): net1=" + net1 + ", mDisabled1=" + mDisabled1
+ + ", token=" + token + ", mDisableRecords=" + mDisableRecords.size() + " => "
+ + disabledData);
+ }
+
if (net1 != mDisabled1 || net2 != mDisabled2) {
mDisabled1 = net1;
mDisabled2 = net2;
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 61e14143f162..1c08d039207b 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -383,7 +383,7 @@ class ActivityMetricsLogger {
return;
}
- if (launchedActivity != null && launchedActivity.nowVisible) {
+ if (launchedActivity != null && launchedActivity.mDrawn) {
// Launched activity is already visible. We cannot measure windows drawn delay.
reset(true /* abort */, info, "launched activity already visible");
return;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 23f812559566..c43e64ec5b98 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -20,6 +20,7 @@ import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.TaskDescription.ATTR_TASKDESCRIPTION_PREFIX;
import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
import static android.app.ActivityTaskManager.INVALID_STACK_ID;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
import static android.app.WaitResult.INVALID_DELAY;
@@ -75,20 +76,6 @@ import static android.os.Process.SYSTEM_UID;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_FOCUS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_FOCUS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER;
import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
import static com.android.server.am.ActivityRecordProto.IDENTIFIER;
@@ -96,6 +83,8 @@ import static com.android.server.am.ActivityRecordProto.PROC_ID;
import static com.android.server.am.ActivityRecordProto.STATE;
import static com.android.server.am.ActivityRecordProto.TRANSLUCENT;
import static com.android.server.am.ActivityRecordProto.VISIBLE;
+import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
+import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
@@ -106,17 +95,28 @@ import static com.android.server.wm.ActivityStack.LAUNCH_TICK;
import static com.android.server.wm.ActivityStack.LAUNCH_TICK_MSG;
import static com.android.server.wm.ActivityStack.PAUSE_TIMEOUT_MSG;
import static com.android.server.wm.ActivityStack.STOP_TIMEOUT_MSG;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_FOCUS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_FOCUS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
-import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
-import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
-import static com.android.server.wm.TaskPersister.DEBUG;
-import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
+import static com.android.server.wm.TaskPersister.DEBUG;
+import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
@@ -179,9 +179,9 @@ import com.android.server.AttributeCache;
import com.android.server.AttributeCache.Entry;
import com.android.server.am.AppTimeTracker;
import com.android.server.am.PendingIntentRecord;
+import com.android.server.uri.UriPermissionOwner;
import com.android.server.wm.ActivityMetricsLogger.WindowingModeTransitionInfoSnapshot;
import com.android.server.wm.ActivityStack.ActivityState;
-import com.android.server.uri.UriPermissionOwner;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -303,6 +303,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
// process that it is hidden.
boolean sleeping; // have we told the activity to sleep?
boolean nowVisible; // is this activity's window visible?
+ boolean mDrawn; // is this activity's window drawn?
boolean mClientVisibilityDeferred;// was the visibility change message to client deferred?
boolean idle; // has the activity gone idle?
boolean hasBeenLaunched;// has this activity ever been launched?
@@ -869,6 +870,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
inHistory = false;
visible = false;
nowVisible = false;
+ mDrawn = false;
idle = false;
hasBeenLaunched = false;
mStackSupervisor = supervisor;
@@ -1944,8 +1946,12 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
}
@Override
- public void onWindowsDrawn(long timestamp) {
+ public void onWindowsDrawn(boolean drawn, long timestamp) {
synchronized (service.mGlobalLock) {
+ mDrawn = drawn;
+ if (!drawn) {
+ return;
+ }
final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
.getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), timestamp);
final int windowsDrawnDelayMs = info != null ? info.windowsDrawnDelayMs : INVALID_DELAY;
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 97eaafcdc622..37a65cd7c901 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -145,6 +145,7 @@ import android.hardware.display.DisplayManager.DisplayListener;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.power.V1_0.PowerHint;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.FactoryTest;
@@ -835,9 +836,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
final boolean supportMultipleInstance = homeInfo.launchMode != LAUNCH_SINGLE_TASK
- && homeInfo.launchMode != LAUNCH_SINGLE_INSTANCE;
+ && homeInfo.launchMode != LAUNCH_SINGLE_INSTANCE
+ && homeInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q;
if (!supportMultipleInstance) {
- // Can't launch home on other displays if it requested to be single instance.
+ // Can't launch home on other displays if it requested to be single instance. Also we
+ // don't allow home applications that target before Q to have multiple home activity
+ // instances because they may not be expected to have multiple home scenario and
+ // haven't explicitly request for single instance.
return false;
}
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 3cbb25776420..bd1460ae4566 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -82,6 +82,7 @@ public class AppWindowContainerController
private final class H extends Handler {
public static final int NOTIFY_WINDOWS_DRAWN = 1;
public static final int NOTIFY_STARTING_WINDOW_DRAWN = 2;
+ public static final int NOTIFY_WINDOWS_NOTDRAWN = 3;
public H(Looper looper) {
super(looper);
@@ -96,16 +97,24 @@ public class AppWindowContainerController
}
if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting drawn in "
+ AppWindowContainerController.this.mToken);
- mListener.onWindowsDrawn(msg.getWhen());
+ mListener.onWindowsDrawn(true /* drawn */, msg.getWhen());
break;
case NOTIFY_STARTING_WINDOW_DRAWN:
if (mListener == null) {
return;
}
- if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting drawn in "
+ if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting starting window drawn in "
+ AppWindowContainerController.this.mToken);
mListener.onStartingWindowDrawn(msg.getWhen());
break;
+ case NOTIFY_WINDOWS_NOTDRAWN:
+ if (mListener == null) {
+ return;
+ }
+ if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting not drawn in "
+ + AppWindowContainerController.this.mToken);
+ mListener.onWindowsDrawn(false /* drawn */, msg.getWhen());
+ break;
default:
break;
}
@@ -762,6 +771,10 @@ public class AppWindowContainerController
mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_WINDOWS_DRAWN));
}
+ void reportWindowsNotDrawn() {
+ mHandler.sendMessage(mHandler.obtainMessage(H.NOTIFY_WINDOWS_NOTDRAWN));
+ }
+
void reportWindowsVisible() {
mHandler.post(mOnWindowsVisible);
}
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerListener.java b/services/core/java/com/android/server/wm/AppWindowContainerListener.java
index 8a39a7408058..ad27669fc030 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerListener.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerListener.java
@@ -18,8 +18,8 @@ package com.android.server.wm;
/** Interface used by the creator of the controller to listen to changes with the container. */
public interface AppWindowContainerListener extends WindowContainerListener {
- /** Called when the windows associated app window container are drawn. */
- void onWindowsDrawn(long timestamp);
+ /** Called when the windows associated app window container drawn state changes. */
+ void onWindowsDrawn(boolean drawn, long timestamp);
/** Called when the windows associated app window container are visible. */
void onWindowsVisible();
/** Called when the windows associated app window container are no longer visible. */
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 3cece11c0f38..92944a02f77a 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -95,6 +95,7 @@ import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayInfo;
import android.view.IApplicationToken;
+import android.view.InputApplicationHandle;
import android.view.RemoteAnimationDefinition;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
@@ -105,7 +106,6 @@ import android.view.animation.Animation;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
-import com.android.server.input.InputApplicationHandle;
import com.android.server.policy.WindowManagerPolicy.StartingSurface;
import com.android.server.wm.WindowManagerService.H;
@@ -366,6 +366,10 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
if (controller != null) {
controller.reportWindowsDrawn();
}
+ } else {
+ if (controller != null) {
+ controller.reportWindowsNotDrawn();
+ }
}
reportedDrawn = nowDrawn;
}
@@ -2015,9 +2019,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
clearThumbnail();
setClientHidden(isHidden() && hiddenRequested);
- if (mService.mInputMethodTarget != null && mService.mInputMethodTarget.mAppToken == this) {
- getDisplayContent().computeImeTarget(true /* updateImeTarget */);
- }
+ getDisplayContent().computeImeTargetIfNeeded(this);
if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
+ ": reportedVisible=" + reportedVisible
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 3accaf8c1f98..cc14afce7ff6 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -126,9 +126,10 @@ class Dimmer {
DimState(SurfaceControl dimLayer) {
mDimLayer = dimLayer;
mDimming = true;
- mSurfaceAnimator = new SurfaceAnimator(new DimAnimatable(dimLayer), () -> {
+ final DimAnimatable dimAnimatable = new DimAnimatable(dimLayer);
+ mSurfaceAnimator = new SurfaceAnimator(dimAnimatable, () -> {
if (!mDimming) {
- mDimLayer.destroy();
+ dimAnimatable.getPendingTransaction().destroy(mDimLayer);
}
}, mHost.mService);
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 767a6ef49414..a3e80294a53c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -100,7 +100,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.CUSTOM_SCREEN_ROTATION;
-import static com.android.server.wm.WindowManagerService.H.REPORT_FOCUS_CHANGE;
import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
@@ -496,6 +495,15 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
*/
WindowState mInputMethodWindow;
+ /**
+ * This just indicates the window the input method is on top of, not
+ * necessarily the window its input is going to.
+ */
+ WindowState mInputMethodTarget;
+
+ /** If true hold off on modifying the animation layer of mInputMethodTarget */
+ boolean mInputMethodTargetWaitingAnim;
+
private final PointerEventDispatcher mPointerEventDispatcher;
private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
@@ -699,7 +707,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
private final Consumer<WindowState> mApplyPostLayoutPolicy =
w -> mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
- mService.mInputMethodTarget);
+ mInputMethodTarget);
private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
@@ -1928,7 +1936,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* rather than directly above their target.
*/
private boolean skipTraverseChild(WindowContainer child) {
- if (child == mImeWindowsContainers && mService.mInputMethodTarget != null
+ if (child == mImeWindowsContainers && mInputMethodTarget != null
&& !hasSplitScreenPrimaryStack()) {
return true;
}
@@ -2800,13 +2808,12 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (mCurrentFocus == newFocus) {
return false;
}
- mService.mH.obtainMessage(REPORT_FOCUS_CHANGE, this).sendToTarget();
boolean imWindowChanged = false;
// TODO (b/111080190): Multi-Session IME
if (!focusFound) {
final WindowState imWindow = mInputMethodWindow;
if (imWindow != null) {
- final WindowState prevTarget = mService.mInputMethodTarget;
+ final WindowState prevTarget = mInputMethodTarget;
final WindowState newTarget = computeImeTarget(true /* updateImeTarget*/);
imWindowChanged = prevTarget != newTarget;
@@ -2998,13 +3005,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// There isn't an IME so there shouldn't be a target...That was easy!
if (updateImeTarget) {
if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from "
- + mService.mInputMethodTarget + " to null since mInputMethodWindow is null");
- setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim);
+ + mInputMethodTarget + " to null since mInputMethodWindow is null");
+ setInputMethodTarget(null, mInputMethodTargetWaitingAnim);
}
return null;
}
- final WindowState curTarget = mService.mInputMethodTarget;
+ final WindowState curTarget = mInputMethodTarget;
if (!canUpdateImeTarget()) {
if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Defer updating IME target");
return curTarget;
@@ -3031,7 +3038,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM,
- "Proposed new IME target: " + target);
+ "Proposed new IME target: " + target + " for display: " + getDisplayId());
// Now, a special case -- if the last target's window is in the process of exiting, but
// not removed, and the new target is home, keep on the last target to avoid flicker.
@@ -3052,7 +3059,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
+ " to null." + (SHOW_STACK_CRAWLS ? " Callers="
+ Debug.getCallers(4) : ""));
- setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim);
+ setInputMethodTarget(null, mInputMethodTargetWaitingAnim);
}
return null;
@@ -3091,14 +3098,23 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
return target;
}
+ /**
+ * Calling {@link #computeImeTarget(boolean)} to update the input method target window in
+ * the candidate app window token if needed.
+ */
+ void computeImeTargetIfNeeded(AppWindowToken candidate) {
+ if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == candidate) {
+ computeImeTarget(true /* updateImeTarget */);
+ }
+ }
+
private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim) {
- if (target == mService.mInputMethodTarget
- && mService.mInputMethodTargetWaitingAnim == targetWaitingAnim) {
+ if (target == mInputMethodTarget && mInputMethodTargetWaitingAnim == targetWaitingAnim) {
return;
}
- mService.mInputMethodTarget = target;
- mService.mInputMethodTargetWaitingAnim = targetWaitingAnim;
+ mInputMethodTarget = target;
+ mInputMethodTargetWaitingAnim = targetWaitingAnim;
assignWindowLayers(false /* setLayoutNeeded */);
}
@@ -4487,7 +4503,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mTaskStackContainers.assignLayer(t, 1);
mAboveAppWindowsContainers.assignLayer(t, 2);
- WindowState imeTarget = mService.mInputMethodTarget;
+ final WindowState imeTarget = mInputMethodTarget;
boolean needAssignIme = true;
// In the case where we have an IME target that is not in split-screen
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index ce8c979d3f87..7ed078a93375 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -36,7 +36,7 @@ import android.view.SurfaceSession;
import android.view.View;
import com.android.internal.util.Preconditions;
-import com.android.server.input.InputWindowHandle;
+import android.view.InputWindowHandle;
import com.android.server.wm.WindowManagerInternal.IDragDropCallback;
import java.util.concurrent.atomic.AtomicReference;
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 5483602487a2..a379266fe533 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -57,8 +57,8 @@ import android.view.animation.Interpolator;
import com.android.internal.view.IDragAndDropPermissions;
import com.android.server.LocalServices;
-import com.android.server.input.InputApplicationHandle;
-import com.android.server.input.InputWindowHandle;
+import android.view.InputApplicationHandle;
+import android.view.InputWindowHandle;
import java.util.ArrayList;
@@ -223,7 +223,7 @@ class DragState {
mDragApplicationHandle.dispatchingTimeoutNanos =
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
- mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null, null,
+ mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
display.getDisplayId());
mDragWindowHandle.name = "drag";
mDragWindowHandle.inputChannel = mServerChannel;
diff --git a/services/core/java/com/android/server/wm/InputConsumerImpl.java b/services/core/java/com/android/server/wm/InputConsumerImpl.java
index 585a4f55c9c2..49bedc97a38a 100644
--- a/services/core/java/com/android/server/wm/InputConsumerImpl.java
+++ b/services/core/java/com/android/server/wm/InputConsumerImpl.java
@@ -23,8 +23,8 @@ import android.os.UserHandle;
import android.view.InputChannel;
import android.view.WindowManager;
-import com.android.server.input.InputApplicationHandle;
-import com.android.server.input.InputWindowHandle;
+import android.view.InputApplicationHandle;
+import android.view.InputWindowHandle;
import java.io.PrintWriter;
@@ -63,7 +63,7 @@ class InputConsumerImpl implements IBinder.DeathRecipient {
mApplicationHandle.dispatchingTimeoutNanos =
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
- mWindowHandle = new InputWindowHandle(mApplicationHandle, null, null, displayId);
+ mWindowHandle = new InputWindowHandle(mApplicationHandle, null, displayId);
mWindowHandle.name = name;
mWindowHandle.inputChannel = mServerChannel;
mWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index f823caadad79..92ea1a90735c 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -8,16 +8,19 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.app.ActivityManager;
import android.os.Debug;
+import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import android.view.KeyEvent;
import android.view.WindowManager;
-import com.android.server.input.InputApplicationHandle;
+import android.view.InputApplicationHandle;
import com.android.server.input.InputManagerService;
-import com.android.server.input.InputWindowHandle;
+import android.view.InputWindowHandle;
+import android.view.InputChannel;
import java.io.PrintWriter;
+import java.util.HashMap;
final class InputManagerCallback implements InputManagerService.WindowManagerCallbacks {
private final WindowManagerService mService;
@@ -48,13 +51,13 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
* Called by the InputManager.
*/
@Override
- public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
- if (inputWindowHandle == null) {
+ public void notifyInputChannelBroken(IBinder token) {
+ if (token == null) {
return;
}
synchronized (mService.mGlobalLock) {
- WindowState windowState = (WindowState) inputWindowHandle.windowState;
+ WindowState windowState = mService.windowForClientLocked(null, token, false);
if (windowState != null) {
Slog.i(TAG_WM, "WINDOW DIED " + windowState);
windowState.removeIfPossible();
@@ -70,13 +73,13 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
*/
@Override
public long notifyANR(InputApplicationHandle inputApplicationHandle,
- InputWindowHandle inputWindowHandle, String reason) {
+ IBinder token, String reason) {
AppWindowToken appWindowToken = null;
WindowState windowState = null;
boolean aboveSystem = false;
synchronized (mService.mGlobalLock) {
- if (inputWindowHandle != null) {
- windowState = (WindowState) inputWindowHandle.windowState;
+ if (token != null) {
+ windowState = mService.windowForClientLocked(null, token, false);
if (windowState != null) {
appWindowToken = windowState.mAppToken;
}
@@ -188,8 +191,8 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
*/
@Override
public long interceptKeyBeforeDispatching(
- InputWindowHandle focus, KeyEvent event, int policyFlags) {
- WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
+ IBinder focus, KeyEvent event, int policyFlags) {
+ WindowState windowState = mService.windowForClientLocked(null, focus, false);
return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
}
@@ -199,8 +202,8 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
*/
@Override
public KeyEvent dispatchUnhandledKey(
- InputWindowHandle focus, KeyEvent event, int policyFlags) {
- WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
+ IBinder focus, KeyEvent event, int policyFlags) {
+ WindowState windowState = mService.windowForClientLocked(null, focus, false);
return mService.mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 0e4ab53e5c56..61bc4e405385 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -42,9 +42,12 @@ import android.util.Log;
import android.util.Slog;
import android.view.InputChannel;
import android.view.InputEventReceiver;
+import android.view.KeyEvent;
+import android.view.WindowManager;
+import android.view.InputApplicationHandle;
+import android.view.InputWindowHandle;
-import com.android.server.input.InputApplicationHandle;
-import com.android.server.input.InputWindowHandle;
+import com.android.server.input.InputManagerService;
import com.android.server.policy.WindowManagerPolicy;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index c4fbee931df3..6627c2dc5cc3 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -43,6 +43,7 @@ import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.proto.ProtoOutputStream;
+import android.view.InputWindowHandle;
import android.view.IRecentsAnimationController;
import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationTarget;
@@ -50,7 +51,6 @@ import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
-import com.android.server.input.InputWindowHandle;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
import com.android.server.wm.utils.InsetUtils;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 01b05c38df67..1baca321d01d 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -122,7 +122,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
// The ID of the display which is responsible for receiving display-unspecified key and pointer
// events.
- private int mTopFocusedDisplayId = INVALID_DISPLAY;
+ int mTopFocusedDisplayId = INVALID_DISPLAY;
// Only a seperate transaction until we seperate the apply surface changes
// transaction from the global transaction.
@@ -156,7 +156,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
boolean changed = false;
int topFocusedDisplayId = INVALID_DISPLAY;
- for (int i = mChildren.size() - 1; i >= 0; i--) {
+
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
final DisplayContent dc = mChildren.get(i);
changed |= dc.updateFocusedWindowLocked(mode, updateInputWindows,
topFocusedDisplayId != INVALID_DISPLAY /* focusFound */);
@@ -167,12 +168,35 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
if (topFocusedDisplayId == INVALID_DISPLAY) {
topFocusedDisplayId = DEFAULT_DISPLAY;
}
+ // TODO(b/118865114): Review if need callback top focus display change to view component.
+ // (i.e. Activity or View)
+ // Currently we only tracked topFocusedDisplayChanged for notifying InputMethodManager via
+ // ViewRootImpl.windowFocusChanged to refocus IME window when top display focus changed
+ // but window focus remain the same case.
+ // It may need to review if any use case that need to add new callback for reporting
+ // this change.
+ final boolean topFocusedDisplayChanged =
+ mTopFocusedDisplayId != topFocusedDisplayId && mode == UPDATE_FOCUS_NORMAL;
if (mTopFocusedDisplayId != topFocusedDisplayId) {
mTopFocusedDisplayId = topFocusedDisplayId;
- mService.mInputManager.setFocusedDisplay(topFocusedDisplayId);
+ mService.mInputManager.setFocusedDisplay(mTopFocusedDisplayId);
if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "New topFocusedDisplayId="
- + topFocusedDisplayId);
- }
+ + mTopFocusedDisplayId);
+ }
+
+ // Report window focus or top display focus changed through REPORT_FOCUS_CHANGE.
+ forAllDisplays((dc) -> {
+ final boolean windowFocusChanged =
+ dc.mCurrentFocus != null && dc.mCurrentFocus != dc.mLastFocus;
+ final boolean isTopFocusedDisplay =
+ topFocusedDisplayChanged && dc.getDisplayId() == mTopFocusedDisplayId;
+ if (windowFocusChanged || isTopFocusedDisplay) {
+ final Message msg = mService.mH.obtainMessage(
+ WindowManagerService.H.REPORT_FOCUS_CHANGE, dc);
+ msg.arg1 = topFocusedDisplayChanged ? 1 : 0;
+ mService.mH.sendMessage(msg);
+ }
+ });
final WindowState topFocusedWindow = getTopFocusedDisplayContent().mCurrentFocus;
mService.mInputManager.setFocusedWindow(
topFocusedWindow != null ? topFocusedWindow.mInputWindowHandle : null);
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 66ebc9b27358..7182ad6fccfe 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -49,8 +49,9 @@ import android.view.MotionEvent;
import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.input.InputApplicationHandle;
-import com.android.server.input.InputWindowHandle;
+import android.view.InputApplicationHandle;
+import android.view.InputWindowHandle;
+import com.android.server.wm.WindowManagerService.H;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -265,7 +266,7 @@ class TaskPositioner {
mDragApplicationHandle.dispatchingTimeoutNanos =
WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
- mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null, null,
+ mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
display.getDisplayId());
mDragWindowHandle.name = TAG;
mDragWindowHandle.inputChannel = mServerChannel;
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index f2d3dca27cf9..51567a0d6ad0 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -29,7 +29,7 @@ import android.view.IWindow;
import com.android.internal.annotations.GuardedBy;
import com.android.server.input.InputManagerService;
-import com.android.server.input.InputWindowHandle;
+import android.view.InputWindowHandle;
/**
* Controller for task positioning by drag.
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 073601ddefc6..912cb7fe449a 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -809,7 +809,7 @@ public class TaskStack extends WindowContainer<Task> implements
updateBoundsForDisplayChanges();
}
- if (mAnimationBackgroundSurface != null) {
+ if (mAnimationBackgroundSurface == null) {
mAnimationBackgroundSurface = makeChildSurface(null).setColorLayer(true)
.setName("animation background stackId=" + mStackId)
.build();
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 02904d413b35..d7d3e714eb81 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -623,13 +623,6 @@ public class WindowManagerService extends IWindowManager.Stub
*/
final Handler mAnimationHandler = new Handler(AnimationThread.getHandler().getLooper());
- /** This just indicates the window the input method is on top of, not
- * necessarily the window its input is going to. */
- WindowState mInputMethodTarget = null;
-
- /** If true hold off on modifying the animation layer of mInputMethodTarget */
- boolean mInputMethodTargetWaitingAnim;
-
boolean mHardKeyboardAvailable;
WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
SettingsObserver mSettingsObserver;
@@ -4400,6 +4393,7 @@ public class WindowManagerService extends IWindowManager.Stub
AccessibilityController accessibilityController = null;
+ final boolean topFocusedDisplayChanged = msg.arg1 != 0;
synchronized (mGlobalLock) {
// TODO(multidisplay): Accessibility supported only of default desiplay.
if (mAccessibilityController != null && displayContent.isDefaultDisplay) {
@@ -4409,7 +4403,19 @@ public class WindowManagerService extends IWindowManager.Stub
lastFocus = displayContent.mLastFocus;
newFocus = displayContent.mCurrentFocus;
if (lastFocus == newFocus) {
- // Focus is not changing, so nothing to do.
+ // Report focus to ViewRootImpl when top focused display changes.
+ // Or, nothing to do for no window focus change.
+ if (topFocusedDisplayChanged && newFocus != null) {
+ if (DEBUG_FOCUS_LIGHT) {
+ Slog.d(TAG, "Reporting focus: " + newFocus
+ + " due to top focused display change.");
+ }
+ // See {@link IWindow#windowFocusChanged} to know why set
+ // reportToClient as false.
+ newFocus.reportFocusChangedSerialized(true, mInTouchMode,
+ false /* reportToClient */);
+ notifyFocusChanged();
+ }
return;
}
displayContent.mLastFocus = newFocus;
@@ -4430,13 +4436,15 @@ public class WindowManagerService extends IWindowManager.Stub
if (newFocus != null) {
if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Gaining focus: " + newFocus);
- newFocus.reportFocusChangedSerialized(true, mInTouchMode);
+ newFocus.reportFocusChangedSerialized(true, mInTouchMode,
+ true /* reportToClient */);
notifyFocusChanged();
}
if (lastFocus != null) {
if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing focus: " + lastFocus);
- lastFocus.reportFocusChangedSerialized(false, mInTouchMode);
+ lastFocus.reportFocusChangedSerialized(false, mInTouchMode,
+ true /* reportToClient */);
}
} break;
@@ -4453,7 +4461,8 @@ public class WindowManagerService extends IWindowManager.Stub
for (int i = 0; i < N; i++) {
if (DEBUG_FOCUS_LIGHT) Slog.i(TAG_WM, "Losing delayed focus: " +
losers.get(i));
- losers.get(i).reportFocusChangedSerialized(false, mInTouchMode);
+ losers.get(i).reportFocusChangedSerialized(false, mInTouchMode,
+ true /* reportToClient */);
}
} break;
@@ -5930,9 +5939,13 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(" mGlobalConfiguration="); pw.println(mRoot.getConfiguration());
pw.print(" mHasPermanentDpad="); pw.println(mHasPermanentDpad);
mRoot.dumpTopFocusedDisplayId(pw);
- if (mInputMethodTarget != null) {
- pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
- }
+ mRoot.forAllDisplays(dc -> {
+ final WindowState inputMethodTarget = dc.mInputMethodTarget;
+ if (inputMethodTarget != null) {
+ pw.print(" mInputMethodTarget in display# "); pw.print(dc.getDisplayId());
+ pw.print(' '); pw.println(inputMethodTarget);
+ }
+ });
pw.print(" mInTouchMode="); pw.println(mInTouchMode);
pw.print(" mLastDisplayFreezeDuration=");
TimeUtils.formatDuration(mLastDisplayFreezeDuration, pw);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 99f65c327375..a117cf33e596 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -191,7 +191,7 @@ import android.view.animation.Interpolator;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
-import com.android.server.input.InputWindowHandle;
+import android.view.InputWindowHandle;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
import com.android.server.wm.utils.InsetUtils;
@@ -718,7 +718,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mLastRequestedHeight = 0;
mLayer = 0;
mInputWindowHandle = new InputWindowHandle(
- mAppToken != null ? mAppToken.mInputApplicationHandle : null, this, c,
+ mAppToken != null ? mAppToken.mInputApplicationHandle : null, c,
getDisplayId());
}
@@ -2047,7 +2047,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// Create dummy event receiver that simply reports all events as handled.
mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
}
- mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);
+ mService.mInputManager.registerInputChannel(mInputChannel, mClient.asBinder());
}
void disposeInputChannel() {
@@ -2059,6 +2059,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// unregister server channel first otherwise it complains about broken channel
if (mInputChannel != null) {
mService.mInputManager.unregisterInputChannel(mInputChannel);
+
mInputChannel.dispose();
mInputChannel = null;
}
@@ -2841,12 +2842,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
* Report a focus change. Must be called with no locks held, and consistently
* from the same serialized thread (such as dispatched from a handler).
*/
- void reportFocusChangedSerialized(boolean focused, boolean inTouchMode) {
+ void reportFocusChangedSerialized(boolean focused, boolean inTouchMode,
+ boolean reportToClient) {
try {
- mClient.windowFocusChanged(focused, inTouchMode);
+ mClient.windowFocusChanged(focused, inTouchMode, reportToClient);
} catch (RemoteException e) {
}
- if (mFocusCallbacks != null) {
+ if (mFocusCallbacks != null && reportToClient) {
final int N = mFocusCallbacks.beginBroadcast();
for (int i=0; i<N; i++) {
IWindowFocusObserver obs = mFocusCallbacks.getBroadcastItem(i);
@@ -4476,8 +4478,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
@Override
boolean needsZBoost() {
- if (mIsImWindow && mService.mInputMethodTarget != null) {
- final AppWindowToken appToken = mService.mInputMethodTarget.mAppToken;
+ final WindowState inputMethodTarget = getDisplayContent().mInputMethodTarget;
+ if (mIsImWindow && inputMethodTarget != null) {
+ final AppWindowToken appToken = inputMethodTarget.mAppToken;
if (appToken != null) {
return appToken.needsZBoost();
}
@@ -4607,7 +4610,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// Likewise if we share a token with the Input method target and are ordered
// above it but not necessarily a child (e.g. a Dialog) then we also need
// this promotion.
- final WindowState imeTarget = mService.mInputMethodTarget;
+ final WindowState imeTarget = getDisplayContent().mInputMethodTarget;
boolean inTokenWithAndAboveImeTarget = imeTarget != null && imeTarget != this
&& imeTarget.mToken == mToken && imeTarget.compareTo(this) <= 0;
return inTokenWithAndAboveImeTarget;
@@ -4684,7 +4687,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
@Override
public boolean isInputMethodTarget() {
- return mService.mInputMethodTarget == this;
+ return getDisplayContent().mInputMethodTarget == this;
}
long getFrameNumber() {
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 3943dba7092e..e2db80744294 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -42,6 +42,8 @@
#include <utils/Trace.h>
#include <utils/SortedVector.h>
+#include <binder/IServiceManager.h>
+
#include <input/PointerController.h>
#include <input/SpriteController.h>
@@ -63,6 +65,7 @@
#include "android_hardware_input_InputApplicationHandle.h"
#include "android_hardware_input_InputWindowHandle.h"
#include "android_hardware_display_DisplayViewport.h"
+#include "android_util_Binder.h"
#include <vector>
@@ -153,15 +156,6 @@ static jobject getInputApplicationHandleObjLocalRef(JNIEnv* env,
getInputApplicationHandleObjLocalRef(env);
}
-static jobject getInputWindowHandleObjLocalRef(JNIEnv* env,
- const sp<InputWindowHandle>& inputWindowHandle) {
- if (inputWindowHandle == nullptr) {
- return nullptr;
- }
- return static_cast<NativeInputWindowHandle*>(inputWindowHandle.get())->
- getInputWindowHandleObjLocalRef(env);
-}
-
static void loadSystemIconAsSpriteWithPointerIcon(JNIEnv* env, jobject contextObj, int32_t style,
PointerIcon* outPointerIcon, SpriteIcon* outSpriteIcon) {
status_t status = android_view_PointerIcon_loadSystemIcon(env,
@@ -216,8 +210,7 @@ public:
void setDisplayViewports(JNIEnv* env, jobjectArray viewportObjArray);
- status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
- const sp<InputWindowHandle>& inputWindowHandle, int32_t displayId);
+ status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel, int32_t displayId);
status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
void setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray, int32_t displayId);
@@ -253,17 +246,17 @@ public:
uint32_t policyFlags);
virtual void notifyConfigurationChanged(nsecs_t when);
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputWindowHandle>& inputWindowHandle,
+ const sp<IBinder>& token,
const std::string& reason);
- virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle);
+ virtual void notifyInputChannelBroken(const sp<IBinder>& token);
virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags);
virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig);
virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
virtual nsecs_t interceptKeyBeforeDispatching(
- const sp<InputWindowHandle>& inputWindowHandle,
+ const sp<IBinder>& token,
const KeyEvent* keyEvent, uint32_t policyFlags);
- virtual bool dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
+ virtual bool dispatchUnhandledKey(const sp<IBinder>& token,
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent);
virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType);
virtual bool checkInjectEventsPermissionNonReentrant(
@@ -442,11 +435,10 @@ void NativeInputManager::setDisplayViewports(JNIEnv* env, jobjectArray viewportO
}
status_t NativeInputManager::registerInputChannel(JNIEnv* /* env */,
- const sp<InputChannel>& inputChannel, const sp<InputWindowHandle>& inputWindowHandle,
- int32_t displayId) {
+ const sp<InputChannel>& inputChannel, int32_t displayId) {
ATRACE_CALL();
- return mInputManager->getDispatcher()->registerInputChannel(inputChannel, inputWindowHandle,
- displayId);
+ return mInputManager->getDispatcher()->registerInputChannel(
+ inputChannel, displayId);
}
status_t NativeInputManager::unregisterInputChannel(JNIEnv* /* env */,
@@ -657,7 +649,7 @@ void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
}
nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputWindowHandle>& inputWindowHandle, const std::string& reason) {
+ const sp<IBinder>& token, const std::string& reason) {
#if DEBUG_INPUT_DISPATCHER_POLICY
ALOGD("notifyANR");
#endif
@@ -667,12 +659,11 @@ nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApp
jobject inputApplicationHandleObj =
getInputApplicationHandleObjLocalRef(env, inputApplicationHandle);
- jobject inputWindowHandleObj =
- getInputWindowHandleObjLocalRef(env, inputWindowHandle);
+ jobject tokenObj = javaObjectForIBinder(env, token);
jstring reasonObj = env->NewStringUTF(reason.c_str());
jlong newTimeout = env->CallLongMethod(mServiceObj,
- gServiceClassInfo.notifyANR, inputApplicationHandleObj, inputWindowHandleObj,
+ gServiceClassInfo.notifyANR, inputApplicationHandleObj, tokenObj,
reasonObj);
if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
newTimeout = 0; // abort dispatch
@@ -681,12 +672,11 @@ nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApp
}
env->DeleteLocalRef(reasonObj);
- env->DeleteLocalRef(inputWindowHandleObj);
env->DeleteLocalRef(inputApplicationHandleObj);
return newTimeout;
}
-void NativeInputManager::notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) {
+void NativeInputManager::notifyInputChannelBroken(const sp<IBinder>& token) {
#if DEBUG_INPUT_DISPATCHER_POLICY
ALOGD("notifyInputChannelBroken");
#endif
@@ -694,14 +684,11 @@ void NativeInputManager::notifyInputChannelBroken(const sp<InputWindowHandle>& i
JNIEnv* env = jniEnv();
- jobject inputWindowHandleObj =
- getInputWindowHandleObjLocalRef(env, inputWindowHandle);
- if (inputWindowHandleObj) {
+ jobject tokenObj = javaObjectForIBinder(env, token);
+ if (tokenObj) {
env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyInputChannelBroken,
- inputWindowHandleObj);
+ tokenObj);
checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
-
- env->DeleteLocalRef(inputWindowHandleObj);
}
}
@@ -1061,7 +1048,7 @@ void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,
}
nsecs_t NativeInputManager::interceptKeyBeforeDispatching(
- const sp<InputWindowHandle>& inputWindowHandle,
+ const sp<IBinder>& token,
const KeyEvent* keyEvent, uint32_t policyFlags) {
ATRACE_CALL();
// Policy:
@@ -1072,13 +1059,14 @@ nsecs_t NativeInputManager::interceptKeyBeforeDispatching(
if (policyFlags & POLICY_FLAG_TRUSTED) {
JNIEnv* env = jniEnv();
- // Note: inputWindowHandle may be null.
- jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
+ // Token may be null
+ jobject tokenObj = javaObjectForIBinder(env, token);
+
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
if (keyEventObj) {
jlong delayMillis = env->CallLongMethod(mServiceObj,
gServiceClassInfo.interceptKeyBeforeDispatching,
- inputWindowHandleObj, keyEventObj, policyFlags);
+ tokenObj, keyEventObj, policyFlags);
bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
android_view_KeyEvent_recycle(env, keyEventObj);
env->DeleteLocalRef(keyEventObj);
@@ -1092,12 +1080,11 @@ nsecs_t NativeInputManager::interceptKeyBeforeDispatching(
} else {
ALOGE("Failed to obtain key event object for interceptKeyBeforeDispatching.");
}
- env->DeleteLocalRef(inputWindowHandleObj);
}
return result;
}
-bool NativeInputManager::dispatchUnhandledKey(const sp<InputWindowHandle>& inputWindowHandle,
+bool NativeInputManager::dispatchUnhandledKey(const sp<IBinder>& token,
const KeyEvent* keyEvent, uint32_t policyFlags, KeyEvent* outFallbackKeyEvent) {
ATRACE_CALL();
// Policy:
@@ -1106,13 +1093,13 @@ bool NativeInputManager::dispatchUnhandledKey(const sp<InputWindowHandle>& input
if (policyFlags & POLICY_FLAG_TRUSTED) {
JNIEnv* env = jniEnv();
- // Note: inputWindowHandle may be null.
- jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
+ // Note: tokenObj may be null.
+ jobject tokenObj = javaObjectForIBinder(env, token);
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
if (keyEventObj) {
jobject fallbackKeyEventObj = env->CallObjectMethod(mServiceObj,
gServiceClassInfo.dispatchUnhandledKey,
- inputWindowHandleObj, keyEventObj, policyFlags);
+ tokenObj, keyEventObj, policyFlags);
if (checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey")) {
fallbackKeyEventObj = nullptr;
}
@@ -1131,7 +1118,6 @@ bool NativeInputManager::dispatchUnhandledKey(const sp<InputWindowHandle>& input
} else {
ALOGE("Failed to obtain key event object for dispatchUnhandledKey.");
}
- env->DeleteLocalRef(inputWindowHandleObj);
}
return result;
}
@@ -1316,7 +1302,7 @@ static void handleInputChannelDisposed(JNIEnv* env,
}
static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
- jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jint displayId) {
+ jlong ptr, jobject inputChannelObj, jint displayId) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
@@ -1325,12 +1311,10 @@ static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
throwInputChannelNotInitialized(env);
return;
}
+ bool monitor = inputChannel->getToken() == nullptr && displayId != ADISPLAY_ID_NONE;
- sp<InputWindowHandle> inputWindowHandle =
- android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
+ status_t status = im->registerInputChannel(env, inputChannel, displayId);
- status_t status = im->registerInputChannel(
- env, inputChannel, inputWindowHandle, displayId);
if (status) {
std::string message;
message += StringPrintf("Failed to register input channel. status=%d", status);
@@ -1339,7 +1323,7 @@ static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
}
// If inputWindowHandle is null and displayId >= 0, treat inputChannel as monitor.
- if (inputWindowHandle != nullptr || displayId == ADISPLAY_ID_NONE) {
+ if (!monitor) {
android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
handleInputChannelDisposed, im);
}
@@ -1640,7 +1624,7 @@ static const JNINativeMethod gInputManagerMethods[] = {
{ "nativeHasKeys", "(JII[I[Z)Z",
(void*) nativeHasKeys },
{ "nativeRegisterInputChannel",
- "(JLandroid/view/InputChannel;Lcom/android/server/input/InputWindowHandle;I)V",
+ "(JLandroid/view/InputChannel;I)V",
(void*) nativeRegisterInputChannel },
{ "nativeUnregisterInputChannel", "(JLandroid/view/InputChannel;)V",
(void*) nativeUnregisterInputChannel },
@@ -1650,9 +1634,9 @@ static const JNINativeMethod gInputManagerMethods[] = {
(void*) nativeInjectInputEvent },
{ "nativeToggleCapsLock", "(JI)V",
(void*) nativeToggleCapsLock },
- { "nativeSetInputWindows", "(J[Lcom/android/server/input/InputWindowHandle;I)V",
+ { "nativeSetInputWindows", "(J[Landroid/view/InputWindowHandle;I)V",
(void*) nativeSetInputWindows },
- { "nativeSetFocusedApplication", "(JILcom/android/server/input/InputApplicationHandle;)V",
+ { "nativeSetFocusedApplication", "(JILandroid/view/InputApplicationHandle;)V",
(void*) nativeSetFocusedApplication },
{ "nativeSetFocusedDisplay", "(JI)V",
(void*) nativeSetFocusedDisplay },
@@ -1731,11 +1715,11 @@ int register_android_server_InputManager(JNIEnv* env) {
"notifySwitch", "(JII)V");
GET_METHOD_ID(gServiceClassInfo.notifyInputChannelBroken, clazz,
- "notifyInputChannelBroken", "(Lcom/android/server/input/InputWindowHandle;)V");
+ "notifyInputChannelBroken", "(Landroid/os/IBinder;)V");
GET_METHOD_ID(gServiceClassInfo.notifyANR, clazz,
"notifyANR",
- "(Lcom/android/server/input/InputApplicationHandle;Lcom/android/server/input/InputWindowHandle;Ljava/lang/String;)J");
+ "(Landroid/view/InputApplicationHandle;Landroid/os/IBinder;Ljava/lang/String;)J");
GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz,
"filterInputEvent", "(Landroid/view/InputEvent;I)Z");
@@ -1748,11 +1732,11 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeDispatching, clazz,
"interceptKeyBeforeDispatching",
- "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)J");
+ "(Landroid/os/IBinder;Landroid/view/KeyEvent;I)J");
GET_METHOD_ID(gServiceClassInfo.dispatchUnhandledKey, clazz,
"dispatchUnhandledKey",
- "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
+ "(Landroid/os/IBinder;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
GET_METHOD_ID(gServiceClassInfo.checkInjectEventsPermission, clazz,
"checkInjectEventsPermission", "(II)Z");
diff --git a/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java b/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
index 9cab1ed15b9e..b7d34d7a8025 100644
--- a/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
+++ b/services/intelligence/java/com/android/server/intelligence/ContentCaptureSession.java
@@ -76,7 +76,7 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks
}
/**
- * Cleans up the session and remove itself from the service.
+ * Cleans up the session and removes it from the service.
*
* @param notifyRemoteService whether it should trigger a {@link
* IntelligenceService#onDestroyInteractionSession(InteractionSessionId)}
@@ -85,14 +85,30 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks
@GuardedBy("mLock")
public void removeSelfLocked(boolean notifyRemoteService) {
try {
- if (notifyRemoteService) {
- mRemoteService.onSessionLifecycleRequest(/* context= */ null, mId);
- }
+ destroyLocked(notifyRemoteService);
} finally {
mService.removeSessionLocked(mId);
}
}
+ /**
+ * Cleans up the session, but not removes it from the service.
+ *
+ * @param notifyRemoteService whether it should trigger a {@link
+ * IntelligenceService#onDestroyInteractionSession(InteractionSessionId)}
+ * request.
+ */
+ @GuardedBy("mLock")
+ public void destroyLocked(boolean notifyRemoteService) {
+ if (mService.isVerbose()) {
+ Slog.v(TAG, "destroyLocked(notifyRemoteService=" + notifyRemoteService + ")");
+ }
+ // TODO(b/111276913): must call client to set session as FINISHED_BY_SERVER
+ if (notifyRemoteService) {
+ mRemoteService.onSessionLifecycleRequest(/* context= */ null, mId);
+ }
+ }
+
@Override // from RemoteScreenObservationServiceCallbacks
public void onServiceDied(AbstractRemoteService service) {
// TODO(b/111276913): implement (remove session from PerUserSession?)
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java b/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
index 43d4a4476c11..fcfd24625161 100644
--- a/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
+++ b/services/intelligence/java/com/android/server/intelligence/IntelligenceManagerService.java
@@ -19,6 +19,7 @@ package com.android.server.intelligence;
import static android.content.Context.INTELLIGENCE_MANAGER_SERVICE;
import android.annotation.NonNull;
+import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.content.ComponentName;
import android.content.Context;
@@ -53,18 +54,20 @@ public final class IntelligenceManagerService
@GuardedBy("mLock")
private ActivityManagerInternal mAm;
+ private final LocalService mLocalService = new LocalService();
+
public IntelligenceManagerService(Context context) {
super(context, UserManager.DISALLOW_INTELLIGENCE_CAPTURE);
}
- @Override // from MasterSystemService
+ @Override // from AbstractMasterSystemService
protected String getServiceSettingsProperty() {
// TODO(b/111276913): STOPSHIP temporary settings, until it's set by resourcs + cmd
return "intel_service";
}
- @Override // from MasterSystemService
- protected IntelligencePerUserService newServiceLocked(int resolvedUserId,
+ @Override // from AbstractMasterSystemService
+ protected IntelligencePerUserService newServiceLocked(@UserIdInt int resolvedUserId,
boolean disabled) {
return new IntelligencePerUserService(this, mLock, resolvedUserId);
}
@@ -73,6 +76,13 @@ public final class IntelligenceManagerService
public void onStart() {
publishBinderService(INTELLIGENCE_MANAGER_SERVICE,
new IntelligenceManagerServiceStub());
+ publishLocalService(IntelligenceManagerInternal.class, mLocalService);
+ }
+
+ @Override // from AbstractMasterSystemService
+ protected void onServiceRemoved(@NonNull IntelligencePerUserService service,
+ @UserIdInt int userId) {
+ service.destroyLocked();
}
private ActivityManagerInternal getAmInternal() {
@@ -139,4 +149,19 @@ public final class IntelligenceManagerService
}
}
}
+
+ private final class LocalService extends IntelligenceManagerInternal {
+
+ @Override
+ public boolean isIntelligenceServiceForUser(int uid, int userId) {
+ synchronized (mLock) {
+ final IntelligencePerUserService service = peekServiceForUserLocked(userId);
+ if (service != null) {
+ return service.isIntelligenceServiceForUserLocked(uid);
+ }
+ }
+
+ return false;
+ }
+ }
}
diff --git a/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java b/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
index 584b872c64d0..471b40f82d45 100644
--- a/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
+++ b/services/intelligence/java/com/android/server/intelligence/IntelligencePerUserService.java
@@ -88,12 +88,18 @@ final class IntelligencePerUserService
@NonNull ComponentName componentName, int taskId, int displayId,
@NonNull InteractionSessionId sessionId, int flags,
@NonNull IResultReceiver resultReceiver) {
+ if (!isEnabledLocked()) {
+ sendToClient(resultReceiver, IntelligenceManager.STATE_DISABLED);
+ return;
+ }
final ComponentName serviceComponentName = getServiceComponentName();
if (serviceComponentName == null) {
// TODO(b/111276913): this happens when the system service is starting, we should
// probably handle it in a more elegant way (like waiting for boot_complete or
// something like that
- Slog.w(TAG, "startSession(" + activityToken + "): hold your horses");
+ if (mMaster.debug) {
+ Slog.d(TAG, "startSession(" + activityToken + "): hold your horses");
+ }
return;
}
@@ -128,9 +134,15 @@ final class IntelligencePerUserService
// TODO(b/111276913): log metrics
@GuardedBy("mLock")
public void finishSessionLocked(@NonNull InteractionSessionId sessionId) {
+ if (!isEnabledLocked()) {
+ return;
+ }
+
final ContentCaptureSession session = mSessions.get(sessionId);
if (session == null) {
- Slog.w(TAG, "finishSession(): no session with id" + sessionId);
+ if (mMaster.debug) {
+ Slog.d(TAG, "finishSession(): no session with id" + sessionId);
+ }
return;
}
if (mMaster.verbose) {
@@ -139,12 +151,19 @@ final class IntelligencePerUserService
session.removeSelfLocked(true);
}
+ // TODO(b/111276913): need to figure out why some events are sent before session is started;
+ // probably because IntelligenceManager is not buffering them until it gets the session back
@GuardedBy("mLock")
public void sendEventsLocked(@NonNull InteractionSessionId sessionId,
@NonNull List<ContentCaptureEvent> events) {
+ if (!isEnabledLocked()) {
+ return;
+ }
final ContentCaptureSession session = mSessions.get(sessionId);
if (session == null) {
- Slog.w(TAG, "sendEvents(): no session for " + sessionId);
+ if (mMaster.verbose) {
+ Slog.v(TAG, "sendEvents(): no session for " + sessionId);
+ }
return;
}
if (mMaster.verbose) {
@@ -158,6 +177,27 @@ final class IntelligencePerUserService
mSessions.remove(sessionId);
}
+ @GuardedBy("mLock")
+ public boolean isIntelligenceServiceForUserLocked(int uid) {
+ return uid == getServiceUidLocked();
+ }
+
+ /**
+ * Destroys the service and all state associated with it.
+ *
+ * <p>Called when the service was disabled (for example, if the settings change).
+ */
+ @GuardedBy("mLock")
+ public void destroyLocked() {
+ if (mMaster.debug) Slog.d(TAG, "destroyLocked()");
+ final int numSessions = mSessions.size();
+ for (int i = 0; i < numSessions; i++) {
+ final ContentCaptureSession session = mSessions.valueAt(i);
+ session.destroyLocked(true);
+ }
+ mSessions.clear();
+ }
+
@Override
protected void dumpLocked(String prefix, PrintWriter pw) {
super.dumpLocked(prefix, pw);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 73990f800ac1..3bb8ce3afd74 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -35,6 +35,7 @@ import android.content.res.Configuration;
import android.content.res.Resources.Theme;
import android.database.sqlite.SQLiteCompatibilityWalFlags;
import android.database.sqlite.SQLiteGlobal;
+import android.hardware.display.ColorDisplayManager;
import android.hardware.display.DisplayManagerInternal;
import android.os.BaseBundle;
import android.os.Binder;
@@ -62,7 +63,6 @@ import android.util.TimingsTraceLog;
import android.view.WindowManager;
import com.android.internal.R;
-import com.android.internal.app.ColorDisplayController;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.BinderInternal;
@@ -150,6 +150,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
public final class SystemServer {
+
private static final String TAG = "SystemServer";
// Tag for timing measurement of main thread.
@@ -263,9 +264,8 @@ public final class SystemServer {
private static final int sMaxBinderThreads = 31;
/**
- * Default theme used by the system context. This is used to style
- * system-provided dialogs, such as the Power Off dialog, and other
- * visual content.
+ * Default theme used by the system context. This is used to style system-provided dialogs, such
+ * as the Power Off dialog, and other visual content.
*/
private static final int DEFAULT_SYSTEM_THEME =
com.android.internal.R.style.Theme_DeviceDefault_System;
@@ -306,8 +306,7 @@ public final class SystemServer {
private static native void startSensorService();
/**
- * Start all HIDL services that are run inside the system server. This
- * may take some time.
+ * Start all HIDL services that are run inside the system server. This may take some time.
*/
private static native void startHidlServices();
@@ -343,7 +342,7 @@ public final class SystemServer {
//
// Default the timezone property to GMT if not set.
//
- String timezoneProperty = SystemProperties.get("persist.sys.timezone");
+ String timezoneProperty = SystemProperties.get("persist.sys.timezone");
if (timezoneProperty == null || timezoneProperty.isEmpty()) {
Slog.w(TAG, "Timezone not set; setting to GMT.");
SystemProperties.set("persist.sys.timezone", "GMT");
@@ -424,7 +423,7 @@ public final class SystemServer {
// Prepare the main looper thread (this thread).
android.os.Process.setThreadPriority(
- android.os.Process.THREAD_PRIORITY_FOREGROUND);
+ android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
Looper.prepareMainLooper();
Looper.getMainLooper().setSlowLogThresholdMs(
@@ -529,7 +528,7 @@ public final class SystemServer {
if (filename != null && filename.startsWith("/data")) {
if (!new File(BLOCK_MAP_FILE).exists()) {
Slog.e(TAG, "Can't find block map file, uncrypt failed or " +
- "unexpected runtime restart?");
+ "unexpected runtime restart?");
return;
}
}
@@ -562,11 +561,10 @@ public final class SystemServer {
}
/**
- * Starts the small tangle of critical services that are needed to get
- * the system off the ground. These services have complex mutual dependencies
- * which is why we initialize them all in one place here. Unless your service
- * is also entwined in these dependencies, it should be initialized in one of
- * the other functions.
+ * Starts the small tangle of critical services that are needed to get the system off the
+ * ground. These services have complex mutual dependencies which is why we initialize them all
+ * in one place here. Unless your service is also entwined in these dependencies, it should be
+ * initialized in one of the other functions.
*/
private void startBootstrapServices() {
Slog.i(TAG, "Reading configuration...");
@@ -783,8 +781,7 @@ public final class SystemServer {
}
/**
- * Starts a miscellaneous grab bag of stuff that has yet to be refactored
- * and organized.
+ * Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
*/
private void startOtherServices() {
final Context context = mSystemContext;
@@ -795,7 +792,7 @@ public final class SystemServer {
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
ConnectivityService connectivity = null;
- NsdService serviceDiscovery= null;
+ NsdService serviceDiscovery = null;
WindowManagerService wm = null;
SerialService serial = null;
NetworkTimeUpdateService networkTimeUpdater = null;
@@ -984,7 +981,7 @@ public final class SystemServer {
} else if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
Slog.i(TAG, "No Bluetooth Service (factory test)");
} else if (!context.getPackageManager().hasSystemFeature
- (PackageManager.FEATURE_BLUETOOTH)) {
+ (PackageManager.FEATURE_BLUETOOTH)) {
Slog.i(TAG, "No Bluetooth Service (Bluetooth Hardware Not Present)");
} else {
traceBeginAndSlog("StartBluetoothService");
@@ -1098,7 +1095,7 @@ public final class SystemServer {
try {
mSystemServiceManager.startService(LOCK_SETTINGS_SERVICE_CLASS);
lockSettings = ILockSettings.Stub.asInterface(
- ServiceManager.getService("lock_settings"));
+ ServiceManager.getService("lock_settings"));
} catch (Throwable e) {
reportWtf("starting LockSettingsService service", e);
}
@@ -1139,6 +1136,13 @@ public final class SystemServer {
traceEnd();
}
+ if (!disableIntelligence) {
+ traceBeginAndSlog("StartIntelligenceService");
+ mSystemServiceManager.startService(INTELLIGENCE_MANAGER_SERVICE_CLASS);
+ traceEnd();
+ }
+
+ // NOTE: ClipboardService indirectly depends on IntelligenceService
traceBeginAndSlog("StartClipboardService");
mSystemServiceManager.startService(ClipboardService.class);
traceEnd();
@@ -1167,7 +1171,8 @@ public final class SystemServer {
if (!disableSystemTextClassifier) {
traceBeginAndSlog("StartTextClassificationManagerService");
- mSystemServiceManager.startService(TextClassificationManagerService.Lifecycle.class);
+ mSystemServiceManager
+ .startService(TextClassificationManagerService.Lifecycle.class);
traceEnd();
}
@@ -1196,41 +1201,41 @@ public final class SystemServer {
if (!mOnlyCore) {
if (context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_WIFI)) {
+ PackageManager.FEATURE_WIFI)) {
// Wifi Service must be started first for wifi-related services.
traceBeginAndSlog("StartWifi");
mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
traceEnd();
traceBeginAndSlog("StartWifiScanning");
mSystemServiceManager.startService(
- "com.android.server.wifi.scanner.WifiScanningService");
+ "com.android.server.wifi.scanner.WifiScanningService");
traceEnd();
}
if (context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_WIFI_RTT)) {
+ PackageManager.FEATURE_WIFI_RTT)) {
traceBeginAndSlog("StartRttService");
mSystemServiceManager.startService(
- "com.android.server.wifi.rtt.RttService");
+ "com.android.server.wifi.rtt.RttService");
traceEnd();
}
if (context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_WIFI_AWARE)) {
+ PackageManager.FEATURE_WIFI_AWARE)) {
traceBeginAndSlog("StartWifiAware");
mSystemServiceManager.startService(WIFI_AWARE_SERVICE_CLASS);
traceEnd();
}
if (context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_WIFI_DIRECT)) {
+ PackageManager.FEATURE_WIFI_DIRECT)) {
traceBeginAndSlog("StartWifiP2P");
mSystemServiceManager.startService(WIFI_P2P_SERVICE_CLASS);
traceEnd();
}
if (context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_LOWPAN)) {
+ PackageManager.FEATURE_LOWPAN)) {
traceBeginAndSlog("StartLowpan");
mSystemServiceManager.startService(LOWPAN_SERVICE_CLASS);
traceEnd();
@@ -1238,7 +1243,7 @@ public final class SystemServer {
}
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
- mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
+ mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
traceBeginAndSlog("StartEthernet");
mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
traceEnd();
@@ -1247,10 +1252,10 @@ public final class SystemServer {
traceBeginAndSlog("StartConnectivityService");
try {
connectivity = new ConnectivityService(
- context, networkManagement, networkStats, networkPolicy);
+ context, networkManagement, networkStats, networkPolicy);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity,
- /* allowIsolated= */ false,
- DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
+ /* allowIsolated= */ false,
+ DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
networkStats.bindConnectivityManager(connectivity);
networkPolicy.bindConnectivityManager(connectivity);
} catch (Throwable e) {
@@ -1262,7 +1267,7 @@ public final class SystemServer {
try {
serviceDiscovery = NsdService.create(context);
ServiceManager.addService(
- Context.NSD_SERVICE, serviceDiscovery);
+ Context.NSD_SERVICE, serviceDiscovery);
} catch (Throwable e) {
reportWtf("starting Service Discovery Service", e);
}
@@ -1280,7 +1285,7 @@ public final class SystemServer {
traceBeginAndSlog("StartUpdateLockService");
try {
ServiceManager.addService(Context.UPDATE_LOCK_SERVICE,
- new UpdateLockService(context));
+ new UpdateLockService(context));
} catch (Throwable e) {
reportWtf("starting UpdateLockService", e);
}
@@ -1398,9 +1403,9 @@ public final class SystemServer {
}
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)
- || mPackageManager.hasSystemFeature(
- PackageManager.FEATURE_USB_ACCESSORY)
- || isEmulator) {
+ || mPackageManager.hasSystemFeature(
+ PackageManager.FEATURE_USB_ACCESSORY)
+ || isEmulator) {
// Manage USB host and device support
traceBeginAndSlog("StartUsbService");
mSystemServiceManager.startService(USB_SERVICE_CLASS);
@@ -1432,7 +1437,7 @@ public final class SystemServer {
try {
hardwarePropertiesService = new HardwarePropertiesManagerService(context);
ServiceManager.addService(Context.HARDWARE_PROPERTIES_SERVICE,
- hardwarePropertiesService);
+ hardwarePropertiesService);
} catch (Throwable e) {
Slog.e(TAG, "Failure starting HardwarePropertiesManagerService", e);
}
@@ -1442,8 +1447,8 @@ public final class SystemServer {
mSystemServiceManager.startService(TwilightService.class);
traceEnd();
- if (ColorDisplayController.isAvailable(context)) {
- traceBeginAndSlog("StartNightDisplay");
+ if (ColorDisplayManager.isNightDisplayAvailable(context)) {
+ traceBeginAndSlog("StartColorDisplay");
mSystemServiceManager.startService(ColorDisplayService.class);
traceEnd();
}
@@ -1467,7 +1472,7 @@ public final class SystemServer {
}
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)
- || context.getResources().getBoolean(R.bool.config_enableAppWidgetService)) {
+ || context.getResources().getBoolean(R.bool.config_enableAppWidgetService)) {
traceBeginAndSlog("StartAppWidgetService");
mSystemServiceManager.startService(APPWIDGET_SERVICE_CLASS);
traceEnd();
@@ -1553,7 +1558,7 @@ public final class SystemServer {
traceBeginAndSlog("AddGraphicsStatsService");
ServiceManager.addService(GraphicsStatsService.GRAPHICS_STATS_SERVICE,
- new GraphicsStatsService(context));
+ new GraphicsStatsService(context));
traceEnd();
if (CoverageService.ENABLED) {
@@ -1769,12 +1774,6 @@ public final class SystemServer {
traceEnd();
}
- if (!disableIntelligence) {
- traceBeginAndSlog("StartIntelligenceService");
- mSystemServiceManager.startService(INTELLIGENCE_MANAGER_SERVICE_CLASS);
- traceEnd();
- }
-
traceBeginAndSlog("AppServiceManager");
mSystemServiceManager.startService(AppBindingService.Lifecycle.class);
traceEnd();
@@ -1825,7 +1824,7 @@ public final class SystemServer {
// propagate to it.
final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY);
DisplayMetrics metrics = new DisplayMetrics();
- WindowManager w = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+ WindowManager w = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
w.getDefaultDisplay().getMetrics(metrics);
context.getResources().updateConfiguration(config, metrics);
@@ -1949,7 +1948,9 @@ public final class SystemServer {
traceEnd();
traceBeginAndSlog("MakeNetworkManagementServiceReady");
try {
- if (networkManagementF != null) networkManagementF.systemReady();
+ if (networkManagementF != null) {
+ networkManagementF.systemReady();
+ }
} catch (Throwable e) {
reportWtf("making Network Managment Service ready", e);
}
@@ -1961,21 +1962,27 @@ public final class SystemServer {
traceEnd();
traceBeginAndSlog("MakeIpSecServiceReady");
try {
- if (ipSecServiceF != null) ipSecServiceF.systemReady();
+ if (ipSecServiceF != null) {
+ ipSecServiceF.systemReady();
+ }
} catch (Throwable e) {
reportWtf("making IpSec Service ready", e);
}
traceEnd();
traceBeginAndSlog("MakeNetworkStatsServiceReady");
try {
- if (networkStatsF != null) networkStatsF.systemReady();
+ if (networkStatsF != null) {
+ networkStatsF.systemReady();
+ }
} catch (Throwable e) {
reportWtf("making Network Stats Service ready", e);
}
traceEnd();
traceBeginAndSlog("MakeConnectivityServiceReady");
try {
- if (connectivityF != null) connectivityF.systemReady();
+ if (connectivityF != null) {
+ connectivityF.systemReady();
+ }
} catch (Throwable e) {
reportWtf("making Connectivity Service ready", e);
}
@@ -2010,21 +2017,27 @@ public final class SystemServer {
traceBeginAndSlog("MakeLocationServiceReady");
try {
- if (locationF != null) locationF.systemRunning();
+ if (locationF != null) {
+ locationF.systemRunning();
+ }
} catch (Throwable e) {
reportWtf("Notifying Location Service running", e);
}
traceEnd();
traceBeginAndSlog("MakeCountryDetectionServiceReady");
try {
- if (countryDetectorF != null) countryDetectorF.systemRunning();
+ if (countryDetectorF != null) {
+ countryDetectorF.systemRunning();
+ }
} catch (Throwable e) {
reportWtf("Notifying CountryDetectorService running", e);
}
traceEnd();
traceBeginAndSlog("MakeNetworkTimeUpdateReady");
try {
- if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
+ if (networkTimeUpdaterF != null) {
+ networkTimeUpdaterF.systemRunning();
+ }
} catch (Throwable e) {
reportWtf("Notifying NetworkTimeService running", e);
}
@@ -2032,28 +2045,36 @@ public final class SystemServer {
traceBeginAndSlog("MakeInputManagerServiceReady");
try {
// TODO(BT) Pass parameter to input manager
- if (inputManagerF != null) inputManagerF.systemRunning();
+ if (inputManagerF != null) {
+ inputManagerF.systemRunning();
+ }
} catch (Throwable e) {
reportWtf("Notifying InputManagerService running", e);
}
traceEnd();
traceBeginAndSlog("MakeTelephonyRegistryReady");
try {
- if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
+ if (telephonyRegistryF != null) {
+ telephonyRegistryF.systemRunning();
+ }
} catch (Throwable e) {
reportWtf("Notifying TelephonyRegistry running", e);
}
traceEnd();
traceBeginAndSlog("MakeMediaRouterServiceReady");
try {
- if (mediaRouterF != null) mediaRouterF.systemRunning();
+ if (mediaRouterF != null) {
+ mediaRouterF.systemRunning();
+ }
} catch (Throwable e) {
reportWtf("Notifying MediaRouterService running", e);
}
traceEnd();
traceBeginAndSlog("MakeMmsServiceReady");
try {
- if (mmsServiceF != null) mmsServiceF.systemRunning();
+ if (mmsServiceF != null) {
+ mmsServiceF.systemRunning();
+ }
} catch (Throwable e) {
reportWtf("Notifying MmsService running", e);
}
@@ -2065,7 +2086,9 @@ public final class SystemServer {
// in the build and should reliably be there.
final IIncidentManager incident = IIncidentManager.Stub.asInterface(
ServiceManager.getService(Context.INCIDENT_SERVICE));
- if (incident != null) incident.systemRunning();
+ if (incident != null) {
+ incident.systemRunning();
+ }
} catch (Throwable e) {
reportWtf("Notifying incident daemon running", e);
}
@@ -2076,7 +2099,7 @@ public final class SystemServer {
static final void startSystemUi(Context context, WindowManagerService windowManager) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.systemui",
- "com.android.systemui.SystemUIService"));
+ "com.android.systemui.SystemUIService"));
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
//Slog.d(TAG, "Starting service: " + intent);
context.startServiceAsUser(intent, UserHandle.SYSTEM);
diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk
index 9ab06a129d88..565152c31448 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -27,7 +27,8 @@ LOCAL_PRIVILEGED_MODULE := true
LOCAL_STATIC_JAVA_LIBRARIES := \
services.backup \
- services.core
+ services.core \
+ services.net
include $(BUILD_PACKAGE)
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunkerTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunkerTest.java
new file mode 100644
index 000000000000..77b734785424
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/ContentDefinedChunkerTest.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup.encryption.chunking.cdc;
+
+import static com.android.server.backup.testing.CryptoTestUtils.generateAesKey;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Random;
+
+import javax.crypto.SecretKey;
+
+/** Tests for {@link ContentDefinedChunker}. */
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class ContentDefinedChunkerTest {
+ private static final int WINDOW_SIZE_BYTES = 31;
+ private static final int MIN_SIZE_BYTES = 40;
+ private static final int MAX_SIZE_BYTES = 300;
+ private static final String CHUNK_BOUNDARY = "<----------BOUNDARY----------->";
+ private static final byte[] CHUNK_BOUNDARY_BYTES = CHUNK_BOUNDARY.getBytes(UTF_8);
+ private static final String CHUNK_1 = "This is the first chunk";
+ private static final String CHUNK_2 = "And this is the second chunk";
+ private static final String CHUNK_3 = "And finally here is the third chunk";
+ private static final String SMALL_CHUNK = "12345678";
+
+ private FingerprintMixer mFingerprintMixer;
+ private RabinFingerprint64 mRabinFingerprint64;
+ private ContentDefinedChunker mChunker;
+
+ /** Set up a {@link ContentDefinedChunker} and dependencies for use in the tests. */
+ @Before
+ public void setUp() throws Exception {
+ SecretKey secretKey = generateAesKey();
+ byte[] salt = new byte[FingerprintMixer.SALT_LENGTH_BYTES];
+ Random random = new Random();
+ random.nextBytes(salt);
+ mFingerprintMixer = new FingerprintMixer(secretKey, salt);
+
+ mRabinFingerprint64 = new RabinFingerprint64();
+ long chunkBoundaryFingerprint = calculateFingerprint(CHUNK_BOUNDARY_BYTES);
+ mChunker =
+ new ContentDefinedChunker(
+ MIN_SIZE_BYTES,
+ MAX_SIZE_BYTES,
+ mRabinFingerprint64,
+ mFingerprintMixer,
+ (fingerprint) -> fingerprint == chunkBoundaryFingerprint);
+ }
+
+ /**
+ * Creating a {@link ContentDefinedChunker} with a minimum chunk size that is smaller than the
+ * window size should throw an {@link IllegalArgumentException}.
+ */
+ @Test
+ public void create_withMinChunkSizeSmallerThanWindowSize_throwsIllegalArgumentException() {
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ new ContentDefinedChunker(
+ WINDOW_SIZE_BYTES - 1,
+ MAX_SIZE_BYTES,
+ mRabinFingerprint64,
+ mFingerprintMixer,
+ null));
+ }
+
+ /**
+ * Creating a {@link ContentDefinedChunker} with a maximum chunk size that is smaller than the
+ * minimum chunk size should throw an {@link IllegalArgumentException}.
+ */
+ @Test
+ public void create_withMaxChunkSizeSmallerThanMinChunkSize_throwsIllegalArgumentException() {
+ assertThrows(
+ IllegalArgumentException.class,
+ () ->
+ new ContentDefinedChunker(
+ MIN_SIZE_BYTES,
+ MIN_SIZE_BYTES - 1,
+ mRabinFingerprint64,
+ mFingerprintMixer,
+ null));
+ }
+
+ /**
+ * {@link ContentDefinedChunker#chunkify(InputStream, Chunker.ChunkConsumer)} should split the
+ * input stream across chunk boundaries by default.
+ */
+ @Test
+ public void chunkify_withLargeChunks_splitsIntoChunksAcrossBoundaries() throws Exception {
+ byte[] input =
+ (CHUNK_1 + CHUNK_BOUNDARY + CHUNK_2 + CHUNK_BOUNDARY + CHUNK_3).getBytes(UTF_8);
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(input);
+ ArrayList<String> result = new ArrayList<>();
+
+ mChunker.chunkify(inputStream, (chunk) -> result.add(new String(chunk, UTF_8)));
+
+ assertThat(result)
+ .containsExactly(CHUNK_1 + CHUNK_BOUNDARY, CHUNK_2 + CHUNK_BOUNDARY, CHUNK_3)
+ .inOrder();
+ }
+
+ /** Chunks should be combined across boundaries until they reach the minimum chunk size. */
+ @Test
+ public void chunkify_withSmallChunks_combinesChunksUntilMinSize() throws Exception {
+ byte[] input =
+ (SMALL_CHUNK + CHUNK_BOUNDARY + CHUNK_2 + CHUNK_BOUNDARY + CHUNK_3).getBytes(UTF_8);
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(input);
+ ArrayList<String> result = new ArrayList<>();
+
+ mChunker.chunkify(inputStream, (chunk) -> result.add(new String(chunk, UTF_8)));
+
+ assertThat(result)
+ .containsExactly(SMALL_CHUNK + CHUNK_BOUNDARY + CHUNK_2 + CHUNK_BOUNDARY, CHUNK_3)
+ .inOrder();
+ assertThat(result.get(0).length()).isAtLeast(MIN_SIZE_BYTES);
+ }
+
+ /** Chunks can not be larger than the maximum chunk size. */
+ @Test
+ public void chunkify_doesNotProduceChunksLargerThanMaxSize() throws Exception {
+ byte[] largeInput = new byte[MAX_SIZE_BYTES * 10];
+ Arrays.fill(largeInput, "a".getBytes(UTF_8)[0]);
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(largeInput);
+ ArrayList<String> result = new ArrayList<>();
+
+ mChunker.chunkify(inputStream, (chunk) -> result.add(new String(chunk, UTF_8)));
+
+ byte[] expectedChunkBytes = new byte[MAX_SIZE_BYTES];
+ Arrays.fill(expectedChunkBytes, "a".getBytes(UTF_8)[0]);
+ String expectedChunk = new String(expectedChunkBytes, UTF_8);
+ assertThat(result)
+ .containsExactly(
+ expectedChunk,
+ expectedChunk,
+ expectedChunk,
+ expectedChunk,
+ expectedChunk,
+ expectedChunk,
+ expectedChunk,
+ expectedChunk,
+ expectedChunk,
+ expectedChunk)
+ .inOrder();
+ }
+
+ /**
+ * If the input stream signals zero availablility, {@link
+ * ContentDefinedChunker#chunkify(InputStream, Chunker.ChunkConsumer)} should still work.
+ */
+ @Test
+ public void chunkify_withInputStreamReturningZeroAvailability_returnsChunks() throws Exception {
+ byte[] input = (SMALL_CHUNK + CHUNK_BOUNDARY + CHUNK_2).getBytes(UTF_8);
+ ZeroAvailabilityInputStream zeroAvailabilityInputStream =
+ new ZeroAvailabilityInputStream(input);
+ ArrayList<String> result = new ArrayList<>();
+
+ mChunker.chunkify(
+ zeroAvailabilityInputStream, (chunk) -> result.add(new String(chunk, UTF_8)));
+
+ assertThat(result).containsExactly(SMALL_CHUNK + CHUNK_BOUNDARY + CHUNK_2).inOrder();
+ }
+
+ /**
+ * {@link ContentDefinedChunker#chunkify(InputStream, Chunker.ChunkConsumer)} should rethrow any
+ * exception thrown by its consumer.
+ */
+ @Test
+ public void chunkify_whenConsumerThrowsException_rethrowsException() throws Exception {
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(new byte[] {1});
+
+ assertThrows(
+ GeneralSecurityException.class,
+ () ->
+ mChunker.chunkify(
+ inputStream,
+ (chunk) -> {
+ throw new GeneralSecurityException();
+ }));
+ }
+
+ private long calculateFingerprint(byte[] bytes) {
+ long fingerprint = 0;
+ for (byte inByte : bytes) {
+ fingerprint =
+ mRabinFingerprint64.computeFingerprint64(
+ /*inChar=*/ inByte, /*outChar=*/ (byte) 0, fingerprint);
+ }
+ return mFingerprintMixer.mix(fingerprint);
+ }
+
+ private static class ZeroAvailabilityInputStream extends ByteArrayInputStream {
+ ZeroAvailabilityInputStream(byte[] wrapped) {
+ super(wrapped);
+ }
+
+ @Override
+ public synchronized int available() {
+ return 0;
+ }
+ }
+}
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/FingerprintMixerTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/FingerprintMixerTest.java
new file mode 100644
index 000000000000..936b5dca033d
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/FingerprintMixerTest.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup.encryption.chunking.cdc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.util.HashSet;
+import java.util.Random;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+/** Tests for {@link FingerprintMixer}. */
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class FingerprintMixerTest {
+ private static final String KEY_ALGORITHM = "AES";
+ private static final int SEED = 42;
+ private static final int SALT_LENGTH_BYTES = 256 / 8;
+ private static final int KEY_SIZE_BITS = 256;
+
+ private Random mSeededRandom;
+ private FingerprintMixer mFingerprintMixer;
+
+ /** Set up a {@link FingerprintMixer} with deterministic key and salt generation. */
+ @Before
+ public void setUp() throws Exception {
+ // Seed so that the tests are deterministic.
+ mSeededRandom = new Random(SEED);
+ mFingerprintMixer = new FingerprintMixer(randomKey(), randomSalt());
+ }
+
+ /**
+ * Construcing a {@link FingerprintMixer} with a salt that is too small should throw an {@link
+ * IllegalArgumentException}.
+ */
+ @Test
+ public void create_withIncorrectSaltSize_throwsIllegalArgumentException() {
+ byte[] tooSmallSalt = new byte[SALT_LENGTH_BYTES - 1];
+
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> new FingerprintMixer(randomKey(), tooSmallSalt));
+ }
+
+ /**
+ * Constructing a {@link FingerprintMixer} with a secret key that can't be encoded should throw
+ * an {@link InvalidKeyException}.
+ */
+ @Test
+ public void create_withUnencodableSecretKey_throwsInvalidKeyException() {
+ byte[] keyBytes = new byte[KEY_SIZE_BITS / 8];
+ UnencodableSecretKeySpec keySpec =
+ new UnencodableSecretKeySpec(keyBytes, 0, keyBytes.length, KEY_ALGORITHM);
+
+ assertThrows(InvalidKeyException.class, () -> new FingerprintMixer(keySpec, randomSalt()));
+ }
+
+ /**
+ * {@link FingerprintMixer#getAddend()} should not return the same addend for two different
+ * keys.
+ */
+ @Test
+ public void getAddend_withDifferentKey_returnsDifferentResult() throws Exception {
+ int iterations = 100_000;
+ HashSet<Long> returnedAddends = new HashSet<>();
+ byte[] salt = randomSalt();
+
+ for (int i = 0; i < iterations; i++) {
+ FingerprintMixer fingerprintMixer = new FingerprintMixer(randomKey(), salt);
+ long addend = fingerprintMixer.getAddend();
+ returnedAddends.add(addend);
+ }
+
+ assertThat(returnedAddends).containsNoDuplicates();
+ }
+
+ /**
+ * {@link FingerprintMixer#getMultiplicand()} should not return the same multiplicand for two
+ * different keys.
+ */
+ @Test
+ public void getMultiplicand_withDifferentKey_returnsDifferentResult() throws Exception {
+ int iterations = 100_000;
+ HashSet<Long> returnedMultiplicands = new HashSet<>();
+ byte[] salt = randomSalt();
+
+ for (int i = 0; i < iterations; i++) {
+ FingerprintMixer fingerprintMixer = new FingerprintMixer(randomKey(), salt);
+ long multiplicand = fingerprintMixer.getMultiplicand();
+ returnedMultiplicands.add(multiplicand);
+ }
+
+ assertThat(returnedMultiplicands).containsNoDuplicates();
+ }
+
+ /** The multiplicant returned by {@link FingerprintMixer} should always be odd. */
+ @Test
+ public void getMultiplicand_isOdd() throws Exception {
+ int iterations = 100_000;
+
+ for (int i = 0; i < iterations; i++) {
+ FingerprintMixer fingerprintMixer = new FingerprintMixer(randomKey(), randomSalt());
+
+ long multiplicand = fingerprintMixer.getMultiplicand();
+
+ assertThat(isOdd(multiplicand)).isTrue();
+ }
+ }
+
+ /** {@link FingerprintMixer#mix(long)} should have a random distribution. */
+ @Test
+ public void mix_randomlyDistributesBits() throws Exception {
+ int iterations = 100_000;
+ float tolerance = 0.1f;
+ int[] totals = new int[64];
+
+ for (int i = 0; i < iterations; i++) {
+ long n = mFingerprintMixer.mix(mSeededRandom.nextLong());
+ for (int j = 0; j < 64; j++) {
+ int bit = (int) (n >> j & 1);
+ totals[j] += bit;
+ }
+ }
+
+ for (int i = 0; i < 64; i++) {
+ float mean = ((float) totals[i]) / iterations;
+ float diff = Math.abs(mean - 0.5f);
+ assertThat(diff).isLessThan(tolerance);
+ }
+ }
+
+ /**
+ * {@link FingerprintMixer#mix(long)} should always produce a number that's different from the
+ * input.
+ */
+ @Test
+ public void mix_doesNotProduceSameNumberAsInput() {
+ int iterations = 100_000;
+
+ for (int i = 0; i < iterations; i++) {
+ assertThat(mFingerprintMixer.mix(i)).isNotEqualTo(i);
+ }
+ }
+
+ private byte[] randomSalt() {
+ byte[] salt = new byte[SALT_LENGTH_BYTES];
+ mSeededRandom.nextBytes(salt);
+ return salt;
+ }
+
+ /**
+ * Not a secure way of generating keys. We want to deterministically generate the same keys for
+ * each test run, though, to ensure the test is deterministic.
+ */
+ private SecretKey randomKey() {
+ byte[] keyBytes = new byte[KEY_SIZE_BITS / 8];
+ mSeededRandom.nextBytes(keyBytes);
+ return new SecretKeySpec(keyBytes, 0, keyBytes.length, KEY_ALGORITHM);
+ }
+
+ private static boolean isOdd(long n) {
+ return Math.abs(n % 2) == 1;
+ }
+
+ /**
+ * Subclass of {@link SecretKeySpec} that does not provide an encoded version. As per its
+ * contract in {@link Key}, that means {@code getEncoded()} always returns null.
+ */
+ private class UnencodableSecretKeySpec extends SecretKeySpec {
+ UnencodableSecretKeySpec(byte[] key, int offset, int len, String algorithm) {
+ super(key, offset, len, algorithm);
+ }
+
+ @Override
+ public byte[] getEncoded() {
+ return null;
+ }
+ }
+}
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/HkdfTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/HkdfTest.java
new file mode 100644
index 000000000000..549437454e9c
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/HkdfTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup.encryption.chunking.cdc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+/** Tests for {@link Hkdf}. */
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class HkdfTest {
+ /** HKDF Test Case 1 IKM from RFC 5869 */
+ private static final byte[] HKDF_CASE1_IKM = {
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b
+ };
+
+ /** HKDF Test Case 1 salt from RFC 5869 */
+ private static final byte[] HKDF_CASE1_SALT = {
+ 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x0a, 0x0b, 0x0c
+ };
+
+ /** HKDF Test Case 1 info from RFC 5869 */
+ private static final byte[] HKDF_CASE1_INFO = {
+ (byte) 0xf0, (byte) 0xf1, (byte) 0xf2, (byte) 0xf3, (byte) 0xf4,
+ (byte) 0xf5, (byte) 0xf6, (byte) 0xf7, (byte) 0xf8, (byte) 0xf9
+ };
+
+ /** First 32 bytes of HKDF Test Case 1 OKM (output) from RFC 5869 */
+ private static final byte[] HKDF_CASE1_OKM = {
+ (byte) 0x3c, (byte) 0xb2, (byte) 0x5f, (byte) 0x25, (byte) 0xfa,
+ (byte) 0xac, (byte) 0xd5, (byte) 0x7a, (byte) 0x90, (byte) 0x43,
+ (byte) 0x4f, (byte) 0x64, (byte) 0xd0, (byte) 0x36, (byte) 0x2f,
+ (byte) 0x2a, (byte) 0x2d, (byte) 0x2d, (byte) 0x0a, (byte) 0x90,
+ (byte) 0xcf, (byte) 0x1a, (byte) 0x5a, (byte) 0x4c, (byte) 0x5d,
+ (byte) 0xb0, (byte) 0x2d, (byte) 0x56, (byte) 0xec, (byte) 0xc4,
+ (byte) 0xc5, (byte) 0xbf
+ };
+
+ /** Test the example from RFC 5869. */
+ @Test
+ public void hkdf_derivesKeyMaterial() throws Exception {
+ byte[] result = Hkdf.hkdf(HKDF_CASE1_IKM, HKDF_CASE1_SALT, HKDF_CASE1_INFO);
+
+ assertThat(result).isEqualTo(HKDF_CASE1_OKM);
+ }
+
+ /** Providing a key that is null should throw a {@link java.lang.NullPointerException}. */
+ @Test
+ public void hkdf_withNullKey_throwsNullPointerException() throws Exception {
+ assertThrows(
+ NullPointerException.class,
+ () -> Hkdf.hkdf(null, HKDF_CASE1_SALT, HKDF_CASE1_INFO));
+ }
+
+ /** Providing a salt that is null should throw a {@link java.lang.NullPointerException}. */
+ @Test
+ public void hkdf_withNullSalt_throwsNullPointerException() throws Exception {
+ assertThrows(
+ NullPointerException.class, () -> Hkdf.hkdf(HKDF_CASE1_IKM, null, HKDF_CASE1_INFO));
+ }
+
+ /** Providing data that is null should throw a {@link java.lang.NullPointerException}. */
+ @Test
+ public void hkdf_withNullData_throwsNullPointerException() throws Exception {
+ assertThrows(
+ NullPointerException.class, () -> Hkdf.hkdf(HKDF_CASE1_IKM, HKDF_CASE1_SALT, null));
+ }
+}
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpointTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpointTest.java
new file mode 100644
index 000000000000..277dc372e73c
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/IsChunkBreakpointTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup.encryption.chunking.cdc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.Random;
+
+/** Tests for {@link IsChunkBreakpoint}. */
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class IsChunkBreakpointTest {
+ private static final int RANDOM_SEED = 42;
+ private static final double TOLERANCE = 0.01;
+ private static final int NUMBER_OF_TESTS = 10000;
+ private static final int BITS_PER_LONG = 64;
+
+ private Random mRandom;
+
+ /** Make sure that tests are deterministic. */
+ @Before
+ public void setUp() {
+ mRandom = new Random(RANDOM_SEED);
+ }
+
+ /**
+ * Providing a negative average number of trials should throw an {@link
+ * IllegalArgumentException}.
+ */
+ @Test
+ public void create_withNegativeAverageNumberOfTrials_throwsIllegalArgumentException() {
+ assertThrows(IllegalArgumentException.class, () -> new IsChunkBreakpoint(-1));
+ }
+
+ // Note: the following three tests are compute-intensive, so be cautious adding more.
+
+ /**
+ * If the provided average number of trials is zero, a breakpoint should be expected after one
+ * trial on average.
+ */
+ @Test
+ public void
+ isBreakpoint_withZeroAverageNumberOfTrials_isTrueOnAverageAfterOneTrial() {
+ assertExpectedTrials(new IsChunkBreakpoint(0), /*expectedTrials=*/ 1);
+ }
+
+ /**
+ * If the provided average number of trials is 512, a breakpoint should be expected after 512
+ * trials on average.
+ */
+ @Test
+ public void
+ isBreakpoint_with512AverageNumberOfTrials_isTrueOnAverageAfter512Trials() {
+ assertExpectedTrials(new IsChunkBreakpoint(512), /*expectedTrials=*/ 512);
+ }
+
+ /**
+ * If the provided average number of trials is 1024, a breakpoint should be expected after 1024
+ * trials on average.
+ */
+ @Test
+ public void
+ isBreakpoint_with1024AverageNumberOfTrials_isTrueOnAverageAfter1024Trials() {
+ assertExpectedTrials(new IsChunkBreakpoint(1024), /*expectedTrials=*/ 1024);
+ }
+
+ /** The number of leading zeros should be the logarithm of the average number of trials. */
+ @Test
+ public void getLeadingZeros_squaredIsAverageNumberOfTrials() {
+ for (int i = 0; i < BITS_PER_LONG; i++) {
+ long averageNumberOfTrials = (long) Math.pow(2, i);
+
+ int leadingZeros = new IsChunkBreakpoint(averageNumberOfTrials).getLeadingZeros();
+
+ assertThat(leadingZeros).isEqualTo(i);
+ }
+ }
+
+ private void assertExpectedTrials(IsChunkBreakpoint isChunkBreakpoint, long expectedTrials) {
+ long sum = 0;
+ for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+ sum += numberOfTrialsTillBreakpoint(isChunkBreakpoint);
+ }
+ long averageTrials = sum / NUMBER_OF_TESTS;
+ assertThat((double) Math.abs(averageTrials - expectedTrials))
+ .isLessThan(TOLERANCE * expectedTrials);
+ }
+
+ private int numberOfTrialsTillBreakpoint(IsChunkBreakpoint isChunkBreakpoint) {
+ int trials = 0;
+
+ while (true) {
+ trials++;
+ if (isChunkBreakpoint.isBreakpoint(mRandom.nextLong())) {
+ return trials;
+ }
+ }
+ }
+}
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64Test.java b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64Test.java
new file mode 100644
index 000000000000..729580cf5101
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/cdc/RabinFingerprint64Test.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.backup.encryption.chunking.cdc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.platform.test.annotations.Presubmit;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+/** Tests for {@link RabinFingerprint64}. */
+@RunWith(RobolectricTestRunner.class)
+@Presubmit
+public class RabinFingerprint64Test {
+ private static final int WINDOW_SIZE = 31;
+ private static final ImmutableList<String> TEST_STRINGS =
+ ImmutableList.of(
+ "ervHTtChYXO6eXivYqThlyyzqkbRaOR",
+ "IxaVunH9ZC3qneWfhj1GkBH4ys9CYqz",
+ "wZRVjlE1p976icCFPX9pibk4PEBvjSH",
+ "pHIVaT8x8If9D6s9croksgNmJpmGYWI");
+
+ private final RabinFingerprint64 mRabinFingerprint64 = new RabinFingerprint64();
+
+ /**
+ * No matter where in the input buffer a string occurs, {@link
+ * RabinFingerprint64#computeFingerprint64(byte, byte, long)} should return the same
+ * fingerprint.
+ */
+ @Test
+ public void computeFingerprint64_forSameWindow_returnsSameFingerprint() {
+ long fingerprint1 =
+ computeFingerprintAtPosition(getBytes(TEST_STRINGS.get(0)), WINDOW_SIZE - 1);
+ long fingerprint2 =
+ computeFingerprintAtPosition(
+ getBytes(TEST_STRINGS.get(1), TEST_STRINGS.get(0)), WINDOW_SIZE * 2 - 1);
+ long fingerprint3 =
+ computeFingerprintAtPosition(
+ getBytes(TEST_STRINGS.get(2), TEST_STRINGS.get(3), TEST_STRINGS.get(0)),
+ WINDOW_SIZE * 3 - 1);
+ String stub = "abc";
+ long fingerprint4 =
+ computeFingerprintAtPosition(
+ getBytes(stub, TEST_STRINGS.get(0)), WINDOW_SIZE + stub.length() - 1);
+
+ // Assert that all fingerprints are exactly the same
+ assertThat(ImmutableSet.of(fingerprint1, fingerprint2, fingerprint3, fingerprint4))
+ .hasSize(1);
+ }
+
+ /** The computed fingerprint should be different for different inputs. */
+ @Test
+ public void computeFingerprint64_withDifferentInput_returnsDifferentFingerprint() {
+ long fingerprint1 = computeFingerprintOf(TEST_STRINGS.get(0));
+ long fingerprint2 = computeFingerprintOf(TEST_STRINGS.get(1));
+ long fingerprint3 = computeFingerprintOf(TEST_STRINGS.get(2));
+ long fingerprint4 = computeFingerprintOf(TEST_STRINGS.get(3));
+
+ assertThat(ImmutableList.of(fingerprint1, fingerprint2, fingerprint3, fingerprint4))
+ .containsNoDuplicates();
+ }
+
+ /**
+ * An input with the same characters in a different order should return a different fingerprint.
+ */
+ @Test
+ public void computeFingerprint64_withSameInputInDifferentOrder_returnsDifferentFingerprint() {
+ long fingerprint1 = computeFingerprintOf("abcdefghijklmnopqrstuvwxyz12345");
+ long fingerprint2 = computeFingerprintOf("54321zyxwvutsrqponmlkjihgfedcba");
+ long fingerprint3 = computeFingerprintOf("4bcdefghijklmnopqrstuvwxyz123a5");
+ long fingerprint4 = computeFingerprintOf("bacdefghijklmnopqrstuvwxyz12345");
+
+ assertThat(ImmutableList.of(fingerprint1, fingerprint2, fingerprint3, fingerprint4))
+ .containsNoDuplicates();
+ }
+
+ /** UTF-8 bytes of all the given strings in order. */
+ private byte[] getBytes(String... strings) {
+ StringBuilder sb = new StringBuilder();
+ for (String s : strings) {
+ sb.append(s);
+ }
+ return sb.toString().getBytes(UTF_8);
+ }
+
+ /**
+ * The Rabin fingerprint of a window of bytes ending at {@code position} in the {@code bytes}
+ * array.
+ */
+ private long computeFingerprintAtPosition(byte[] bytes, int position) {
+ assertThat(position).isAtMost(bytes.length - 1);
+ long fingerprint = 0;
+ for (int i = 0; i <= position; i++) {
+ byte outChar;
+ if (i >= WINDOW_SIZE) {
+ outChar = bytes[i - WINDOW_SIZE];
+ } else {
+ outChar = (byte) 0;
+ }
+ fingerprint =
+ mRabinFingerprint64.computeFingerprint64(
+ /*inChar=*/ bytes[i], outChar, fingerprint);
+ }
+ return fingerprint;
+ }
+
+ private long computeFingerprintOf(String s) {
+ assertThat(s.length()).isEqualTo(WINDOW_SIZE);
+ return computeFingerprintAtPosition(s.getBytes(UTF_8), WINDOW_SIZE - 1);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
index ee42ce8b591a..e6b328a128b7 100644
--- a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
@@ -125,7 +125,7 @@ public class StorageManagerServiceTest {
"/storage/emulated/0/foo.jpg",
PID_GREY, UID_GREY);
assertTranslation(
- "/storage/emulated/0/Android/sandbox/shared:colors/foo.jpg",
+ "/storage/emulated/0/Android/sandbox/shared-colors/foo.jpg",
"/storage/emulated/0/foo.jpg",
PID_RED, UID_COLORS);
}
@@ -137,7 +137,7 @@ public class StorageManagerServiceTest {
"/storage/0000-0000/foo/bar.jpg",
PID_GREY, UID_GREY);
assertTranslation(
- "/storage/0000-0000/Android/sandbox/shared:colors/foo/bar.jpg",
+ "/storage/0000-0000/Android/sandbox/shared-colors/foo/bar.jpg",
"/storage/0000-0000/foo/bar.jpg",
PID_RED, UID_COLORS);
}
@@ -152,7 +152,7 @@ public class StorageManagerServiceTest {
// Accessing other package paths goes into sandbox
assertTranslation(
- "/storage/emulated/0/Android/sandbox/shared:colors/"
+ "/storage/emulated/0/Android/sandbox/shared-colors/"
+ "Android/data/com.grey/foo.jpg",
"/storage/emulated/0/Android/data/com.grey/foo.jpg",
PID_RED, UID_COLORS);
@@ -201,7 +201,7 @@ public class StorageManagerServiceTest {
// Sandboxes can't see paths in other sandboxes
try {
mService.translateSystemToApp(
- "/storage/emulated/0/Android/sandbox/shared:colors/foo.jpg",
+ "/storage/emulated/0/Android/sandbox/shared-colors/foo.jpg",
PID_GREY, UID_GREY);
fail();
} catch (SecurityException expected) {
diff --git a/services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java b/services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java
deleted file mode 100644
index c162c3b9cc42..000000000000
--- a/services/tests/servicestests/src/com/android/server/am/GlobalSettingsToPropertiesMapperTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.am;
-
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import android.content.ContentResolver;
-import android.provider.Settings;
-import android.test.mock.MockContentResolver;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.util.Preconditions;
-import com.android.internal.util.test.FakeSettingsProvider;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Tests for {@link GlobalSettingsToPropertiesMapper}
- *
- * Build/Install/Run:
- * atest FrameworksServicesTests:GlobalSettingsToPropertiesMapperTest
- */
-@SmallTest
-public class GlobalSettingsToPropertiesMapperTest {
- private static final String[][] TEST_MAPPING = new String[][] {
- {Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "TestProperty"}
- };
-
- private TestMapper mTestMapper;
- private MockContentResolver mMockContentResolver;
-
- @Before
- public void setup() {
- // Use FakeSettingsProvider to not affect global state
- mMockContentResolver = new MockContentResolver(getInstrumentation().getTargetContext());
- mMockContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
- mTestMapper = new TestMapper(mMockContentResolver);
- }
-
- @Test
- public void testUpdatePropertiesFromGlobalSettings() {
- Settings.Global.putString(mMockContentResolver,
- Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue");
-
- mTestMapper.updatePropertiesFromGlobalSettings();
- String propValue = mTestMapper.systemPropertiesGet("TestProperty");
- assertEquals("testValue", propValue);
-
- Settings.Global.putString(mMockContentResolver,
- Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue2");
- mTestMapper.updatePropertyFromSetting(Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS,
- "TestProperty");
- propValue = mTestMapper.systemPropertiesGet("TestProperty");
- assertEquals("testValue2", propValue);
-
- Settings.Global.putString(mMockContentResolver,
- Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, null);
- mTestMapper.updatePropertyFromSetting(Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS,
- "TestProperty");
- propValue = mTestMapper.systemPropertiesGet("TestProperty");
- assertEquals("", propValue);
- }
-
- @Test
- public void testUpdatePropertiesFromGlobalSettings_PropertyAndSettingNotPresent() {
- // Test that empty property will not not be set if setting is not set
- mTestMapper.updatePropertiesFromGlobalSettings();
- String propValue = mTestMapper.systemPropertiesGet("TestProperty");
- assertNull("Property should not be set if setting is null", propValue);
- }
-
- private static class TestMapper extends GlobalSettingsToPropertiesMapper {
- private final Map<String, String> mProps = new HashMap<>();
-
- TestMapper(ContentResolver contentResolver) {
- super(contentResolver, TEST_MAPPING);
- }
-
- @Override
- protected String systemPropertiesGet(String key) {
- Preconditions.checkNotNull(key);
- return mProps.get(key);
- }
-
- @Override
- protected void systemPropertiesSet(String key, String value) {
- Preconditions.checkNotNull(value);
- Preconditions.checkNotNull(key);
- mProps.put(key, value);
- }
- }
-}
-
diff --git a/services/tests/servicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java b/services/tests/servicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java
new file mode 100644
index 000000000000..d965f8a34fa4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/SettingsToPropertiesMapperTest.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import android.content.ContentResolver;
+import android.provider.Settings;
+import android.test.mock.MockContentResolver;
+import android.text.TextUtils;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.Preconditions;
+import com.android.internal.util.test.FakeSettingsProvider;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Tests for {@link SettingsToPropertiesMapper}
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class SettingsToPropertiesMapperTest {
+ private static final String NAME_VALID_CHARACTERS_REGEX = "^[\\w\\.\\-@:]*$";
+ private static final String[] TEST_MAPPING = new String[] {
+ Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS
+ };
+
+ private TestMapper mTestMapper;
+ private MockContentResolver mMockContentResolver;
+
+ @Before
+ public void setupForEach() {
+ // Use FakeSettingsProvider to not affect global state
+ mMockContentResolver = new MockContentResolver(InstrumentationRegistry.getContext());
+ mMockContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+ mTestMapper = new TestMapper(mMockContentResolver);
+ }
+
+ @Test
+ public void validateRegisteredGlobalSettings() {
+ HashSet<String> hashSet = new HashSet<>();
+ for (String globalSetting : SettingsToPropertiesMapper.sGlobalSettings) {
+ if (hashSet.contains(globalSetting)) {
+ Assert.fail("globalSetting "
+ + globalSetting
+ + " is registered more than once in "
+ + "SettingsToPropertiesMapper.sGlobalSettings.");
+ }
+ hashSet.add(globalSetting);
+ if (TextUtils.isEmpty(globalSetting)) {
+ Assert.fail("empty globalSetting registered.");
+ }
+ if (!globalSetting.matches(NAME_VALID_CHARACTERS_REGEX)) {
+ Assert.fail(globalSetting + " contains invalid characters. "
+ + "Only alphanumeric characters, '.', '-', '@', ':' and '_' are valid.");
+ }
+ }
+ }
+
+ @Test
+ public void testUpdatePropertiesFromSettings() {
+ Settings.Global.putString(mMockContentResolver,
+ Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue");
+
+ String systemPropertyName = "persist.device_config.global_settings."
+ + "sqlite_compatibility_wal_flags";
+
+ mTestMapper.updatePropertiesFromSettings();
+ String propValue = mTestMapper.systemPropertiesGet(systemPropertyName);
+ Assert.assertEquals("testValue", propValue);
+
+ Settings.Global.putString(mMockContentResolver,
+ Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, "testValue2");
+ mTestMapper.updatePropertyFromSetting(
+ Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS,
+ systemPropertyName,
+ true);
+ propValue = mTestMapper.systemPropertiesGet(systemPropertyName);
+ Assert.assertEquals("testValue2", propValue);
+
+ Settings.Global.putString(mMockContentResolver,
+ Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS, null);
+ mTestMapper.updatePropertyFromSetting(
+ Settings.Global.SQLITE_COMPATIBILITY_WAL_FLAGS,
+ systemPropertyName,
+ true);
+ propValue = mTestMapper.systemPropertiesGet(systemPropertyName);
+ Assert.assertEquals("", propValue);
+ }
+
+ @Test
+ public void testMakePropertyName() {
+ try {
+ Assert.assertEquals("persist.device_config.test_category.test_flag",
+ SettingsToPropertiesMapper.makePropertyName("test_category", "test_flag"));
+ } catch (Exception e) {
+ Assert.fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ Assert.assertEquals(null,
+ SettingsToPropertiesMapper.makePropertyName("test_category!!!", "test_flag"));
+ } catch (Exception e) {
+ Assert.fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ Assert.assertEquals(null,
+ SettingsToPropertiesMapper.makePropertyName("test_category", ".test_flag"));
+ } catch (Exception e) {
+ Assert.fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+ @Test
+ public void testUpdatePropertiesFromSettings_PropertyAndSettingNotPresent() {
+ // Test that empty property will not not be set if setting is not set
+ mTestMapper.updatePropertiesFromSettings();
+ String propValue = mTestMapper.systemPropertiesGet("TestProperty");
+ Assert.assertNull("Property should not be set if setting is null", propValue);
+ }
+
+ @Test
+ public void testIsNativeFlagsResetPerformed() {
+ mTestMapper.systemPropertiesSet("device_config.reset_performed", "true");
+ Assert.assertTrue(mTestMapper.isNativeFlagsResetPerformed());
+
+ mTestMapper.systemPropertiesSet("device_config.reset_performed", "false");
+ Assert.assertFalse(mTestMapper.isNativeFlagsResetPerformed());
+
+ mTestMapper.systemPropertiesSet("device_config.reset_performed", "");
+ Assert.assertFalse(mTestMapper.isNativeFlagsResetPerformed());
+ }
+
+ @Test
+ public void testGetResetNativeCategories() {
+ mTestMapper.systemPropertiesSet("device_config.reset_performed", "");
+ Assert.assertEquals(mTestMapper.getResetNativeCategories().length, 0);
+
+ mTestMapper.systemPropertiesSet("device_config.reset_performed", "true");
+ mTestMapper.setFileContent("");
+ Assert.assertEquals(mTestMapper.getResetNativeCategories().length, 0);
+
+ mTestMapper.systemPropertiesSet("device_config.reset_performed", "true");
+ mTestMapper.setFileContent("persist.device_config.category1.flag;"
+ + "persist.device_config.category2.flag;persist.device_config.category3.flag;"
+ + "persist.device_config.category3.flag2");
+ List<String> categories = Arrays.asList(mTestMapper.getResetNativeCategories());
+ Assert.assertEquals(3, categories.size());
+ Assert.assertTrue(categories.contains("category1"));
+ Assert.assertTrue(categories.contains("category2"));
+ Assert.assertTrue(categories.contains("category3"));
+ }
+
+ private static class TestMapper extends SettingsToPropertiesMapper {
+ private final Map<String, String> mProps = new HashMap<>();
+
+ private String mFileContent = "";
+
+ TestMapper(ContentResolver contentResolver) {
+ super(contentResolver, TEST_MAPPING, new String[] {});
+ }
+
+ @Override
+ protected String systemPropertiesGet(String key) {
+ Preconditions.checkNotNull(key);
+ return mProps.get(key);
+ }
+
+ @Override
+ protected void systemPropertiesSet(String key, String value) {
+ Preconditions.checkNotNull(value);
+ Preconditions.checkNotNull(key);
+ mProps.put(key, value);
+ }
+
+ protected void setFileContent(String fileContent) {
+ mFileContent = fileContent;
+ }
+
+ @Override
+ protected String getResetFlagsFileContent() {
+ return mFileContent;
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
index b6a7cfba7dc4..991981f62d30 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
@@ -37,7 +37,7 @@ import org.junit.Test;
/**
* Build/Install/Run:
- * atest FrameworksServicesTests:DimmerTests;
+ * atest FrameworksServicesTests:DimmerTests
*/
@Presubmit
public class DimmerTests extends WindowTestsBase {
@@ -211,7 +211,7 @@ public class DimmerTests extends WindowTestsBase {
mDimmer.updateDims(mTransaction, new Rect());
verify(mSurfaceAnimatorStarter).startAnimation(any(SurfaceAnimator.class), any(
SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean());
- verify(dimLayer).destroy();
+ verify(mHost.getPendingTransaction()).destroy(dimLayer);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index f4da4b338cef..c1655bcdb451 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -40,6 +40,7 @@ import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doNothing;
@@ -108,7 +109,7 @@ public class DisplayContentTests extends WindowTestsBase {
final WindowState imeAppTarget =
createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
- mWm.mInputMethodTarget = imeAppTarget;
+ mDisplayContent.mInputMethodTarget = imeAppTarget;
assertForAllWindowsOrder(Arrays.asList(
mWallpaperWindow,
@@ -124,8 +125,8 @@ public class DisplayContentTests extends WindowTestsBase {
}
@Test
- public void testForAllWindows_WithChildWindowImeTarget() {
- mWm.mInputMethodTarget = mChildAppWindowAbove;
+ public void testForAllWindows_WithChildWindowImeTarget() throws Exception {
+ mDisplayContent.mInputMethodTarget = mChildAppWindowAbove;
assertForAllWindowsOrder(Arrays.asList(
mWallpaperWindow,
@@ -140,8 +141,8 @@ public class DisplayContentTests extends WindowTestsBase {
}
@Test
- public void testForAllWindows_WithStatusBarImeTarget() {
- mWm.mInputMethodTarget = mStatusBarWindow;
+ public void testForAllWindows_WithStatusBarImeTarget() throws Exception {
+ mDisplayContent.mInputMethodTarget = mStatusBarWindow;
assertForAllWindowsOrder(Arrays.asList(
mWallpaperWindow,
@@ -568,6 +569,32 @@ public class DisplayContentTests extends WindowTestsBase {
assertFalse(isOptionsPanelAtRight(landscapeDisplay.getDisplayId()));
}
+ @Test
+ public void testInputMethodTargetUpdateWhenSwitchingOnDisplays() {
+ final DisplayContent newDisplay = createNewDisplay();
+
+ final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
+ final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1");
+ appWin.setHasSurface(true);
+ appWin1.setHasSurface(true);
+
+ // Set current input method window on default display, make sure the input method target
+ // is appWin & null on the other display.
+ mDisplayContent.setInputMethodWindowLocked(mImeWindow);
+ newDisplay.setInputMethodWindowLocked(null);
+ assertTrue("appWin should be IME target window",
+ appWin.equals(mDisplayContent.mInputMethodTarget));
+ assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget);
+
+ // Switch input method window on new display & make sure the input method target also
+ // switched as expected.
+ newDisplay.setInputMethodWindowLocked(mImeWindow);
+ mDisplayContent.setInputMethodWindowLocked(null);
+ assertTrue("appWin1 should be IME target window",
+ appWin1.equals(newDisplay.mInputMethodTarget));
+ assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
+ }
+
private boolean isOptionsPanelAtRight(int displayId) {
return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java b/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
index e8d0a066dade..99deeb9e9397 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
@@ -53,7 +53,8 @@ public class TestIWindow extends IWindow.Stub {
}
@Override
- public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) throws RemoteException {
+ public void windowFocusChanged(boolean hasFocus, boolean inTouchMode, boolean reportToClient)
+ throws RemoteException {
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java
index 2b8b93428701..fcde08e18a6f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java
@@ -52,7 +52,7 @@ public class WindowContainerTraversalTests extends WindowTestsBase {
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
TYPE_BASE_APPLICATION, mDisplayContent, "splitScreenSecondaryWindow");
- mWm.mInputMethodTarget = splitScreenWindow;
+ mDisplayContent.mInputMethodTarget = splitScreenWindow;
Consumer<WindowState> c = mock(Consumer.class);
mDisplayContent.forAllWindows(c, false);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 2abe64dd80a4..53858c7c8905 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -192,7 +192,7 @@ class WindowTestsBase {
mWm.getDefaultDisplayContentLocked().mAppTransition
.removeAppTransitionTimeoutCallbacks();
mWm.mH.removeMessages(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT);
- mWm.mInputMethodTarget = null;
+ mDisplayContent.mInputMethodTarget = null;
}
// Wait until everything is really cleaned up.
diff --git a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
index 3c8ae3cecad6..3dcea75b8ae5 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
@@ -209,7 +209,7 @@ public class ZOrderingTests extends WindowTestsBase {
@Test
public void testAssignWindowLayers_ForImeWithNoTarget() {
- mWm.mInputMethodTarget = null;
+ mDisplayContent.mInputMethodTarget = null;
mDisplayContent.assignChildLayers(mTransaction);
// The Ime has an higher base layer than app windows and lower base layer than system
@@ -227,7 +227,7 @@ public class ZOrderingTests extends WindowTestsBase {
@Test
public void testAssignWindowLayers_ForImeWithAppTarget() {
final WindowState imeAppTarget = createWindow("imeAppTarget");
- mWm.mInputMethodTarget = imeAppTarget;
+ mDisplayContent.mInputMethodTarget = imeAppTarget;
mDisplayContent.assignChildLayers(mTransaction);
@@ -253,7 +253,7 @@ public class ZOrderingTests extends WindowTestsBase {
TYPE_APPLICATION_MEDIA_OVERLAY, imeAppTarget.mToken,
"imeAppTargetChildBelowWindow");
- mWm.mInputMethodTarget = imeAppTarget;
+ mDisplayContent.mInputMethodTarget = imeAppTarget;
mDisplayContent.assignChildLayers(mTransaction);
// Ime should be above all app windows except for child windows that are z-ordered above it
@@ -275,7 +275,7 @@ public class ZOrderingTests extends WindowTestsBase {
final WindowState imeAppTarget = createWindow("imeAppTarget");
final WindowState appAboveImeTarget = createWindow("appAboveImeTarget");
- mWm.mInputMethodTarget = imeAppTarget;
+ mDisplayContent.mInputMethodTarget = imeAppTarget;
mDisplayContent.assignChildLayers(mTransaction);
// Ime should be above all app windows except for non-fullscreen app window above it and
@@ -298,7 +298,7 @@ public class ZOrderingTests extends WindowTestsBase {
mDisplayContent, "imeSystemOverlayTarget",
true /* ownerCanAddInternalSystemWindow */);
- mWm.mInputMethodTarget = imeSystemOverlayTarget;
+ mDisplayContent.mInputMethodTarget = imeSystemOverlayTarget;
mDisplayContent.assignChildLayers(mTransaction);
// The IME target base layer is higher than all window except for the nav bar window, so the
@@ -321,7 +321,7 @@ public class ZOrderingTests extends WindowTestsBase {
@Test
public void testAssignWindowLayers_ForStatusBarImeTarget() {
- mWm.mInputMethodTarget = mStatusBarWindow;
+ mDisplayContent.mInputMethodTarget = mStatusBarWindow;
mDisplayContent.assignChildLayers(mTransaction);
assertWindowHigher(mImeWindow, mChildAppWindowAbove);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
index f17a30ddb1b6..410ab8732a08 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java
@@ -72,7 +72,7 @@ public class NotificationAdjustmentExtractorTest extends UiServiceTestCase {
assertTrue(r.getGroupKey().contains(GroupHelper.AUTOGROUP_KEY));
assertEquals(people, r.getPeopleOverride());
assertEquals(snoozeCriteria, r.getSnoozeCriteria());
- assertEquals(smartActions, r.getSmartActions());
+ assertEquals(smartActions, r.getSystemGeneratedSmartActions());
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
index 9b41fdd9fd68..8690110ca66a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java
@@ -708,14 +708,14 @@ public class NotificationRecordTest extends UiServiceTestCase {
true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
false /* lights */, false /* defaultLights */, groupId /* group */);
NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
- assertNull(record.getSmartActions());
+ assertNull(record.getSystemGeneratedSmartActions());
ArrayList<Notification.Action> smartActions = new ArrayList<>();
smartActions.add(new Notification.Action.Builder(
Icon.createWithResource(getContext(), R.drawable.btn_default),
"text", null).build());
- record.setSmartActions(smartActions);
- assertEquals(smartActions, record.getSmartActions());
+ record.setSystemGeneratedSmartActions(smartActions);
+ assertEquals(smartActions, record.getSystemGeneratedSmartActions());
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 3fe381b0abe2..1a218b23368d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -27,7 +27,6 @@ import static junit.framework.Assert.fail;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -98,7 +97,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
private static final UserHandle USER = UserHandle.of(0);
private static final int UID_O = 1111;
private static final String SYSTEM_PKG = "android";
- private static final int SYSTEM_UID= 1000;
+ private static final int SYSTEM_UID = 1000;
private static final UserHandle USER2 = UserHandle.of(10);
private static final String TEST_CHANNEL_ID = "test_channel_id";
private static final String TEST_AUTHORITY = "test";
@@ -1091,6 +1090,158 @@ public class PreferencesHelperTest extends UiServiceTestCase {
}
@Test
+ public void testGetChannelsBypassingDndCount_noChannelsBypassing() throws Exception {
+ assertEquals(0, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+ USER.getIdentifier()).getList().size());
+ }
+
+ @Test
+ public void testGetChannelsBypassingDnd_noChannelsForUserIdBypassing()
+ throws Exception {
+ int user = 9;
+ NotificationChannel channel = new NotificationChannel("id", "name",
+ NotificationManager.IMPORTANCE_MAX);
+ channel.setBypassDnd(true);
+ mHelper.createNotificationChannel(PKG_N_MR1, 111, channel, true, true);
+
+ assertEquals(0, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+ user).getList().size());
+ }
+
+ @Test
+ public void testGetChannelsBypassingDndCount_oneChannelBypassing_groupBlocked() {
+ int user = USER.getIdentifier();
+ NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+ NotificationChannel channel1 = new NotificationChannel("id1", "name1",
+ NotificationManager.IMPORTANCE_MAX);
+ channel1.setBypassDnd(true);
+ channel1.setGroup(ncg.getId());
+ mHelper.createNotificationChannelGroup(PKG_N_MR1, user, ncg, /* fromTargetApp */ true);
+ mHelper.createNotificationChannel(PKG_N_MR1, user, channel1, true, /*has DND access*/ true);
+
+ assertEquals(1, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+ user).getList().size());
+
+ // disable group
+ ncg.setBlocked(true);
+ mHelper.createNotificationChannelGroup(PKG_N_MR1, user, ncg, /* fromTargetApp */ false);
+ assertEquals(0, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+ user).getList().size());
+ }
+
+ @Test
+ public void testGetChannelsBypassingDndCount_multipleChannelsBypassing() {
+ int user = USER.getIdentifier();
+ NotificationChannel channel1 = new NotificationChannel("id1", "name1",
+ NotificationManager.IMPORTANCE_MAX);
+ NotificationChannel channel2 = new NotificationChannel("id2", "name2",
+ NotificationManager.IMPORTANCE_MAX);
+ NotificationChannel channel3 = new NotificationChannel("id3", "name3",
+ NotificationManager.IMPORTANCE_MAX);
+ channel1.setBypassDnd(true);
+ channel2.setBypassDnd(true);
+ channel3.setBypassDnd(true);
+ // has DND access, so can set bypassDnd attribute
+ mHelper.createNotificationChannel(PKG_N_MR1, user, channel1, true, /*has DND access*/ true);
+ mHelper.createNotificationChannel(PKG_N_MR1, user, channel2, true, true);
+ mHelper.createNotificationChannel(PKG_N_MR1, user, channel3, true, true);
+ assertEquals(3, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+ user).getList().size());
+
+ // block notifications from this app
+ mHelper.setEnabled(PKG_N_MR1, user, false);
+ assertEquals(0, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+ user).getList().size());
+
+ // re-enable notifications from this app
+ mHelper.setEnabled(PKG_N_MR1, user, true);
+ assertEquals(3, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+ user).getList().size());
+
+ // setBypassDnd false for some channels
+ channel1.setBypassDnd(false);
+ channel2.setBypassDnd(false);
+ assertEquals(1, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+ user).getList().size());
+
+ // setBypassDnd false for rest of the channels
+ channel3.setBypassDnd(false);
+ assertEquals(0, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1,
+ user).getList().size());
+ }
+
+ @Test
+ public void testGetAppsBypassingDndCount_noAppsBypassing() throws Exception {
+ assertEquals(0, mHelper.getAppsBypassingDndCount(USER.getIdentifier()));
+ }
+
+ @Test
+ public void testGetAppsBypassingDndCount_noAppsForUserIdBypassing() throws Exception {
+ int user = 9;
+ NotificationChannel channel = new NotificationChannel("id", "name",
+ NotificationManager.IMPORTANCE_MAX);
+ channel.setBypassDnd(true);
+ mHelper.createNotificationChannel(PKG_N_MR1, 111, channel, true, true);
+
+ assertEquals(0, mHelper.getAppsBypassingDndCount(user));
+ }
+
+ @Test
+ public void testGetAppsBypassingDndCount_oneChannelBypassing_groupBlocked() {
+ int user = USER.getIdentifier();
+ NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+ NotificationChannel channel1 = new NotificationChannel("id1", "name1",
+ NotificationManager.IMPORTANCE_MAX);
+ channel1.setBypassDnd(true);
+ channel1.setGroup(ncg.getId());
+ mHelper.createNotificationChannelGroup(PKG_N_MR1, user, ncg, /* fromTargetApp */ true);
+ mHelper.createNotificationChannel(PKG_N_MR1, user, channel1, true, /*has DND access*/ true);
+
+ assertEquals(1, mHelper.getAppsBypassingDndCount(user));
+
+ // disable group
+ ncg.setBlocked(true);
+ mHelper.createNotificationChannelGroup(PKG_N_MR1, user, ncg, /* fromTargetApp */ false);
+ assertEquals(0, mHelper.getAppsBypassingDndCount(user));
+ }
+
+ @Test
+ public void testGetAppsBypassingDndCount_oneAppBypassing() {
+ int user = USER.getIdentifier();
+ NotificationChannel channel1 = new NotificationChannel("id1", "name1",
+ NotificationManager.IMPORTANCE_MAX);
+ NotificationChannel channel2 = new NotificationChannel("id2", "name2",
+ NotificationManager.IMPORTANCE_MAX);
+ NotificationChannel channel3 = new NotificationChannel("id3", "name3",
+ NotificationManager.IMPORTANCE_MAX);
+ channel1.setBypassDnd(true);
+ channel2.setBypassDnd(true);
+ channel3.setBypassDnd(true);
+ // has DND access, so can set bypassDnd attribute
+ mHelper.createNotificationChannel(PKG_N_MR1, user, channel1, true, /*has DND access*/ true);
+ mHelper.createNotificationChannel(PKG_N_MR1, user, channel2, true, true);
+ mHelper.createNotificationChannel(PKG_N_MR1, user, channel3, true, true);
+ assertEquals(1, mHelper.getAppsBypassingDndCount(user));
+
+ // block notifications from this app
+ mHelper.setEnabled(PKG_N_MR1, user, false);
+ assertEquals(0, mHelper.getAppsBypassingDndCount(user)); // no apps can bypass dnd
+
+ // re-enable notifications from this app
+ mHelper.setEnabled(PKG_N_MR1, user, true);
+ assertEquals(1, mHelper.getAppsBypassingDndCount(user));
+
+ // setBypassDnd false for some channels
+ channel1.setBypassDnd(false);
+ channel2.setBypassDnd(false);
+ assertEquals(1, mHelper.getAppsBypassingDndCount(user));
+
+ // setBypassDnd false for rest of the channels
+ channel3.setBypassDnd(false);
+ assertEquals(0, mHelper.getAppsBypassingDndCount(user));
+ }
+
+ @Test
public void testCreateAndDeleteCanChannelsBypassDnd() throws Exception {
// create notification channel that can't bypass dnd
// expected result: areChannelsBypassingDnd = false
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
index f692a571b019..16dd92f5f6c3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
@@ -25,6 +25,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
+import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
@@ -57,6 +58,7 @@ import android.app.WaitResult;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.graphics.Rect;
+import android.os.Build;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.MediumTest;
@@ -433,6 +435,26 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
eq(activity), eq(null /* targetOptions */));
}
+ /**
+ * Tests home activities that targeted sdk before Q cannot start on secondary display.
+ */
+ @Test
+ public void testStartHomeTargetSdkBeforeQ() throws Exception {
+ final TestActivityDisplay secondDisplay = spy(createNewActivityDisplay());
+ mSupervisor.addChild(secondDisplay, POSITION_TOP);
+ doReturn(true).when(secondDisplay).supportsSystemDecorations();
+
+ final ActivityInfo info = new ActivityInfo();
+ info.launchMode = LAUNCH_MULTIPLE;
+ info.applicationInfo = new ApplicationInfo();
+ info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
+ assertTrue(mSupervisor.canStartHomeOnDisplay(info, secondDisplay.mDisplayId,
+ false /* allowInstrumenting */));
+
+ info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
+ assertFalse(mSupervisor.canStartHomeOnDisplay(info, secondDisplay.mDisplayId,
+ false /* allowInstrumenting */));
+ }
/**
* Tests that home activities can be started on the displays that supports system decorations.
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 32875dab465f..94d7dbb49b74 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -915,8 +915,12 @@ class UserUsageStatsService {
return "SCREEN_INTERACTIVE";
case UsageEvents.Event.SCREEN_NON_INTERACTIVE:
return "SCREEN_NON_INTERACTIVE";
+ case UsageEvents.Event.KEYGUARD_SHOWN:
+ return "KEYGUARD_SHOWN";
+ case UsageEvents.Event.KEYGUARD_HIDDEN:
+ return "KEYGUARD_HIDDEN";
default:
- return "UNKNOWN";
+ return "UNKNOWN_TYPE_" + eventType;
}
}
diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc
index 33df6f9c37d7..906d64c1f619 100644
--- a/startop/view_compiler/dex_builder.cc
+++ b/startop/view_compiler/dex_builder.cc
@@ -49,18 +49,27 @@ std::ostream& operator<<(std::ostream& out, const Instruction::Op& opcode) {
case Instruction::Op::kReturn:
out << "kReturn";
return out;
+ case Instruction::Op::kReturnObject:
+ out << "kReturnObject";
+ return out;
case Instruction::Op::kMove:
out << "kMove";
return out;
case Instruction::Op::kInvokeVirtual:
out << "kInvokeVirtual";
return out;
+ case Instruction::Op::kInvokeDirect:
+ out << "kInvokeDirect";
+ return out;
case Instruction::Op::kBindLabel:
out << "kBindLabel";
return out;
case Instruction::Op::kBranchEqz:
out << "kBranchEqz";
return out;
+ case Instruction::Op::kNew:
+ out << "kNew";
+ return out;
}
}
@@ -137,6 +146,9 @@ ir::String* DexBuilder::GetOrAddString(const std::string& string) {
entry = Alloc<ir::String>();
// +1 for null terminator
entry->data = slicer::MemView{buffer.get(), header_length + string.size() + 1};
+ ::dex::u4 const new_index = dex_file_->strings_indexes.AllocateIndex();
+ dex_file_->strings_map[new_index] = entry;
+ entry->orig_index = new_index;
string_data_.push_back(std::move(buffer));
}
return entry;
@@ -161,6 +173,8 @@ ir::Type* DexBuilder::GetOrAddType(const std::string& descriptor) {
ir::Type* type = Alloc<ir::Type>();
type->descriptor = GetOrAddString(descriptor);
types_by_descriptor_[descriptor] = type;
+ type->orig_index = dex_file_->types_indexes.AllocateIndex();
+ dex_file_->types_map[type->orig_index] = type;
return type;
}
@@ -217,9 +231,10 @@ ir::EncodedMethod* MethodBuilder::Encode() {
decl_->prototype->param_types != nullptr ? decl_->prototype->param_types->types.size() : 0;
code->registers = num_registers_ + num_args;
code->ins_count = num_args;
- code->outs_count = decl_->prototype->return_type == dex_->GetOrAddType("V") ? 0 : 1;
EncodeInstructions();
code->instructions = slicer::ArrayView<const ::dex::u2>(buffer_.data(), buffer_.size());
+ size_t const return_count = decl_->prototype->return_type == dex_->GetOrAddType("V") ? 0 : 1;
+ code->outs_count = std::max(return_count, max_args_);
method->code = code;
class_->direct_methods.push_back(method);
@@ -240,8 +255,9 @@ void MethodBuilder::AddInstruction(Instruction instruction) {
void MethodBuilder::BuildReturn() { AddInstruction(Instruction::OpNoArgs(Op::kReturn)); }
-void MethodBuilder::BuildReturn(Value src) {
- AddInstruction(Instruction::OpWithArgs(Op::kReturn, /*destination=*/{}, src));
+void MethodBuilder::BuildReturn(Value src, bool is_object) {
+ AddInstruction(Instruction::OpWithArgs(
+ is_object ? Op::kReturnObject : Op::kReturn, /*destination=*/{}, src));
}
void MethodBuilder::BuildConst4(Value target, int value) {
@@ -249,6 +265,11 @@ void MethodBuilder::BuildConst4(Value target, int value) {
AddInstruction(Instruction::OpWithArgs(Op::kMove, target, Value::Immediate(value)));
}
+void MethodBuilder::BuildConstString(Value target, const std::string& value) {
+ const ir::String* const dex_string = dex_->GetOrAddString(value);
+ AddInstruction(Instruction::OpWithArgs(Op::kMove, target, Value::String(dex_string->orig_index)));
+}
+
void MethodBuilder::EncodeInstructions() {
buffer_.clear();
for (const auto& instruction : instructions_) {
@@ -259,27 +280,32 @@ void MethodBuilder::EncodeInstructions() {
void MethodBuilder::EncodeInstruction(const Instruction& instruction) {
switch (instruction.opcode()) {
case Instruction::Op::kReturn:
- return EncodeReturn(instruction);
+ return EncodeReturn(instruction, ::art::Instruction::RETURN);
+ case Instruction::Op::kReturnObject:
+ return EncodeReturn(instruction, ::art::Instruction::RETURN_OBJECT);
case Instruction::Op::kMove:
return EncodeMove(instruction);
case Instruction::Op::kInvokeVirtual:
- return EncodeInvokeVirtual(instruction);
+ return EncodeInvoke(instruction, art::Instruction::INVOKE_VIRTUAL);
+ case Instruction::Op::kInvokeDirect:
+ return EncodeInvoke(instruction, art::Instruction::INVOKE_DIRECT);
case Instruction::Op::kBindLabel:
return BindLabel(instruction.args()[0]);
case Instruction::Op::kBranchEqz:
return EncodeBranch(art::Instruction::IF_EQZ, instruction);
+ case Instruction::Op::kNew:
+ return EncodeNew(instruction);
}
}
-void MethodBuilder::EncodeReturn(const Instruction& instruction) {
- DCHECK_EQ(Instruction::Op::kReturn, instruction.opcode());
+void MethodBuilder::EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode) {
DCHECK(!instruction.dest().has_value());
if (instruction.args().size() == 0) {
- buffer_.push_back(art::Instruction::RETURN_VOID);
+ Encode10x(art::Instruction::RETURN_VOID);
} else {
- DCHECK(instruction.args().size() == 1);
+ DCHECK_EQ(1, instruction.args().size());
size_t source = RegisterValue(instruction.args()[0]);
- buffer_.push_back(art::Instruction::RETURN | source << 8);
+ Encode11x(opcode, source);
}
}
@@ -294,31 +320,43 @@ void MethodBuilder::EncodeMove(const Instruction& instruction) {
if (source.is_immediate()) {
// TODO: support more registers
DCHECK_LT(RegisterValue(*instruction.dest()), 16);
- DCHECK_LT(source.value(), 16);
- buffer_.push_back(art::Instruction::CONST_4 | (source.value() << 12) |
- (RegisterValue(*instruction.dest()) << 8));
+ Encode11n(art::Instruction::CONST_4, RegisterValue(*instruction.dest()), source.value());
+ } else if (source.is_string()) {
+ constexpr size_t kMaxRegisters = 256;
+ DCHECK_LT(RegisterValue(*instruction.dest()), kMaxRegisters);
+ DCHECK_LT(source.value(), 65536); // make sure we don't need a jumbo string
+ Encode21c(::art::Instruction::CONST_STRING, RegisterValue(*instruction.dest()), source.value());
} else {
UNIMPLEMENTED(FATAL);
}
}
-void MethodBuilder::EncodeInvokeVirtual(const Instruction& instruction) {
- DCHECK_EQ(Instruction::Op::kInvokeVirtual, instruction.opcode());
+void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode) {
+ constexpr size_t kMaxArgs = 5;
- // TODO: support more than one argument (i.e. the this argument) and change this to DCHECK_GE
- DCHECK_EQ(1, instruction.args().size());
+ CHECK_LE(instruction.args().size(), kMaxArgs);
- const Value& this_arg = instruction.args()[0];
+ uint8_t arguments[kMaxArgs]{};
+ for (size_t i = 0; i < instruction.args().size(); ++i) {
+ CHECK(instruction.args()[i].is_variable());
+ arguments[i] = RegisterValue(instruction.args()[i]);
+ }
- size_t real_reg = RegisterValue(this_arg) & 0xf;
- buffer_.push_back(1 << 12 | art::Instruction::INVOKE_VIRTUAL);
- buffer_.push_back(instruction.method_id());
- buffer_.push_back(real_reg);
+ Encode35c(opcode,
+ instruction.args().size(),
+ instruction.method_id(),
+ arguments[0],
+ arguments[1],
+ arguments[2],
+ arguments[3],
+ arguments[4]);
+ // If there is a return value, add a move-result instruction
if (instruction.dest().has_value()) {
- real_reg = RegisterValue(*instruction.dest());
- buffer_.push_back(real_reg << 8 | art::Instruction::MOVE_RESULT);
+ Encode11x(art::Instruction::MOVE_RESULT, RegisterValue(*instruction.dest()));
}
+
+ max_args_ = std::max(max_args_, instruction.args().size());
}
// Encodes a conditional branch that tests a single argument.
@@ -331,9 +369,21 @@ void MethodBuilder::EncodeBranch(art::Instruction::Code op, const Instruction& i
CHECK(branch_target.is_label());
size_t instruction_offset = buffer_.size();
- buffer_.push_back(op | (RegisterValue(test_value) << 8));
- size_t field_offset = buffer_.size();
- buffer_.push_back(LabelValue(branch_target, instruction_offset, field_offset));
+ size_t field_offset = buffer_.size() + 1;
+ Encode21c(
+ op, RegisterValue(test_value), LabelValue(branch_target, instruction_offset, field_offset));
+}
+
+void MethodBuilder::EncodeNew(const Instruction& instruction) {
+ DCHECK_EQ(Instruction::Op::kNew, instruction.opcode());
+ DCHECK(instruction.dest().has_value());
+ DCHECK(instruction.dest()->is_variable());
+ DCHECK_EQ(1, instruction.args().size());
+
+ const Value& type = instruction.args()[0];
+ DCHECK_LT(RegisterValue(*instruction.dest()), 256);
+ DCHECK(type.is_type());
+ Encode21c(::art::Instruction::NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value());
}
size_t MethodBuilder::RegisterValue(const Value& value) const {
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h
index 07441518ea32..adf82bf9a01a 100644
--- a/startop/view_compiler/dex_builder.h
+++ b/startop/view_compiler/dex_builder.h
@@ -110,18 +110,22 @@ class Value {
static constexpr Value Local(size_t id) { return Value{id, Kind::kLocalRegister}; }
static constexpr Value Parameter(size_t id) { return Value{id, Kind::kParameter}; }
static constexpr Value Immediate(size_t value) { return Value{value, Kind::kImmediate}; }
+ static constexpr Value String(size_t value) { return Value{value, Kind::kString}; }
static constexpr Value Label(size_t id) { return Value{id, Kind::kLabel}; }
+ static constexpr Value Type(size_t id) { return Value{id, Kind::kType}; }
bool is_register() const { return kind_ == Kind::kLocalRegister; }
bool is_parameter() const { return kind_ == Kind::kParameter; }
bool is_variable() const { return is_register() || is_parameter(); }
bool is_immediate() const { return kind_ == Kind::kImmediate; }
+ bool is_string() const { return kind_ == Kind::kString; }
bool is_label() const { return kind_ == Kind::kLabel; }
+ bool is_type() const { return kind_ == Kind::kType; }
size_t value() const { return value_; }
private:
- enum class Kind { kLocalRegister, kParameter, kImmediate, kLabel };
+ enum class Kind { kLocalRegister, kParameter, kImmediate, kString, kLabel, kType };
const size_t value_;
const Kind kind_;
@@ -137,7 +141,16 @@ class Instruction {
public:
// The operation performed by this instruction. These are virtual instructions that do not
// correspond exactly to DEX instructions.
- enum class Op { kReturn, kMove, kInvokeVirtual, kBindLabel, kBranchEqz };
+ enum class Op {
+ kReturn,
+ kReturnObject,
+ kMove,
+ kInvokeVirtual,
+ kInvokeDirect,
+ kBindLabel,
+ kBranchEqz,
+ kNew
+ };
////////////////////////
// Named Constructors //
@@ -158,6 +171,12 @@ class Instruction {
Value this_arg, T... args) {
return Instruction{Op::kInvokeVirtual, method_id, dest, this_arg, args...};
}
+ // For direct calls (basically, constructors).
+ template <typename... T>
+ static inline Instruction InvokeDirect(size_t method_id, std::optional<const Value> dest,
+ Value this_arg, T... args) {
+ return Instruction{Op::kInvokeDirect, method_id, dest, this_arg, args...};
+ }
///////////////
// Accessors //
@@ -187,6 +206,12 @@ class Instruction {
// Needed for CHECK_EQ, DCHECK_EQ, etc.
std::ostream& operator<<(std::ostream& out, const Instruction::Op& opcode);
+// Keeps track of information needed to manipulate or call a method.
+struct MethodDeclData {
+ size_t id;
+ ir::MethodDecl* decl;
+};
+
// Tools to help build methods and their bodies.
class MethodBuilder {
public:
@@ -210,19 +235,74 @@ class MethodBuilder {
// return-void
void BuildReturn();
- void BuildReturn(Value src);
+ void BuildReturn(Value src, bool is_object = false);
// const/4
void BuildConst4(Value target, int value);
+ void BuildConstString(Value target, const std::string& value);
+ template <typename... T>
+ void BuildNew(Value target, TypeDescriptor type, Prototype constructor, T... args);
// TODO: add builders for more instructions
private:
void EncodeInstructions();
void EncodeInstruction(const Instruction& instruction);
- void EncodeReturn(const Instruction& instruction);
+
+ // Encodes a return instruction. For instructions with no return value, the opcode field is
+ // ignored. Otherwise, this specifies which return instruction will be used (return,
+ // return-object, etc.)
+ void EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode);
+
void EncodeMove(const Instruction& instruction);
- void EncodeInvokeVirtual(const Instruction& instruction);
+ void EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode);
void EncodeBranch(art::Instruction::Code op, const Instruction& instruction);
+ void EncodeNew(const Instruction& instruction);
+
+ // Low-level instruction format encoding. See
+ // https://source.android.com/devices/tech/dalvik/instruction-formats for documentation of
+ // formats.
+
+ inline void Encode10x(art::Instruction::Code opcode) {
+ // 00|op
+ buffer_.push_back(opcode);
+ }
+
+ inline void Encode11x(art::Instruction::Code opcode, uint8_t a) {
+ // aa|op
+ buffer_.push_back((a << 8) | opcode);
+ }
+
+ inline void Encode11n(art::Instruction::Code opcode, uint8_t a, int8_t b) {
+ // b|a|op
+
+ // Make sure the fields are in bounds (4 bits for a, 4 bits for b).
+ CHECK_LT(a, 16);
+ CHECK_LE(-8, b);
+ CHECK_LT(b, 8);
+
+ buffer_.push_back(((b & 0xf) << 12) | (a << 8) | opcode);
+ }
+
+ inline void Encode21c(art::Instruction::Code opcode, uint8_t a, uint16_t b) {
+ // aa|op|bbbb
+ buffer_.push_back((a << 8) | opcode);
+ buffer_.push_back(b);
+ }
+
+ inline void Encode35c(art::Instruction::Code opcode, size_t a, uint16_t b, uint8_t c, uint8_t d,
+ uint8_t e, uint8_t f, uint8_t g) {
+ // a|g|op|bbbb|f|e|d|c
+
+ CHECK_LE(a, 5);
+ CHECK_LT(c, 16);
+ CHECK_LT(d, 16);
+ CHECK_LT(e, 16);
+ CHECK_LT(f, 16);
+ CHECK_LT(g, 16);
+ buffer_.push_back((a << 12) | (g << 8) | opcode);
+ buffer_.push_back(b);
+ buffer_.push_back((f << 12) | (e << 8) | (d << 4) | c);
+ }
// Converts a register or parameter to its DEX register number.
size_t RegisterValue(const Value& value) const;
@@ -262,6 +342,10 @@ class MethodBuilder {
};
std::vector<LabelData> labels_;
+
+ // During encoding, keep track of the largest number of arguments needed, so we can use it for our
+ // outs count
+ size_t max_args_{0};
};
// A helper to build class definitions.
@@ -281,12 +365,6 @@ class ClassBuilder {
ir::Class* const class_;
};
-// Keeps track of information needed to manipulate or call a method.
-struct MethodDeclData {
- size_t id;
- ir::MethodDecl* decl;
-};
-
// Builds Dex files from scratch.
class DexBuilder {
public:
@@ -355,6 +433,17 @@ class DexBuilder {
std::map<Prototype, ir::Proto*> proto_map_;
};
+template <typename... T>
+void MethodBuilder::BuildNew(Value target, TypeDescriptor type, Prototype constructor, T... args) {
+ MethodDeclData constructor_data{dex_->GetOrDeclareMethod(type, "<init>", constructor)};
+ // allocate the object
+ ir::Type* type_def = dex_->GetOrAddType(type.descriptor());
+ AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kNew, target, Value::Type(type_def->orig_index)));
+ // call the constructor
+ AddInstruction(Instruction::InvokeDirect(constructor_data.id, /*dest=*/{}, target, args...));
+};
+
} // namespace dex
} // namespace startop
diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
index 169c63374cb7..e20f3a9406c0 100644
--- a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
+++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
@@ -50,6 +50,14 @@ public class DexBuilderTest {
}
@Test
+ public void returnInteger5() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("returnInteger5");
+ Assert.assertEquals(5, method.invoke(null));
+ }
+
+ @Test
public void returnParam() throws Exception {
ClassLoader loader = loadDexFile("simple.dex");
Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
@@ -82,4 +90,38 @@ public class DexBuilderTest {
Method method = clazz.getMethod("backwardsBranch");
Assert.assertEquals(2, method.invoke(null));
}
+
+ @Test
+ public void returnNull() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("returnNull");
+ Assert.assertEquals(null, method.invoke(null));
+ }
+
+ @Test
+ public void makeString() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("makeString");
+ Assert.assertEquals("Hello, World!", method.invoke(null));
+ }
+
+ @Test
+ public void returnStringIfZeroAB() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("returnStringIfZeroAB", int.class);
+ Assert.assertEquals("a", method.invoke(null, 0));
+ Assert.assertEquals("b", method.invoke(null, 1));
+ }
+
+ @Test
+ public void returnStringIfZeroBA() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("returnStringIfZeroBA", int.class);
+ Assert.assertEquals("b", method.invoke(null, 0));
+ Assert.assertEquals("a", method.invoke(null, 1));
+ }
}
diff --git a/startop/view_compiler/dex_testcase_generator.cc b/startop/view_compiler/dex_testcase_generator.cc
index c521bf2b8ccf..e2bf43bc1d0c 100644
--- a/startop/view_compiler/dex_testcase_generator.cc
+++ b/startop/view_compiler/dex_testcase_generator.cc
@@ -53,6 +53,19 @@ void GenerateSimpleTestCases(const string& outdir) {
}
return5.Encode();
+ // int return5() { return 5; }
+ auto integer_type{TypeDescriptor::FromClassname("java.lang.Integer")};
+ auto returnInteger5{cbuilder.CreateMethod("returnInteger5", Prototype{integer_type})};
+ [&](MethodBuilder& method) {
+ Value five{method.MakeRegister()};
+ method.BuildConst4(five, 5);
+ Value object{method.MakeRegister()};
+ method.BuildNew(
+ object, integer_type, Prototype{TypeDescriptor::Void(), TypeDescriptor::Int()}, five);
+ method.BuildReturn(object, /*is_object=*/true);
+ }(returnInteger5);
+ returnInteger5.Encode();
+
// // int returnParam(int x) { return x; }
auto returnParam{cbuilder.CreateMethod("returnParam",
Prototype{TypeDescriptor::Int(), TypeDescriptor::Int()})};
@@ -138,6 +151,71 @@ void GenerateSimpleTestCases(const string& outdir) {
}(backwardsBranch);
backwardsBranch.Encode();
+ // Test that we can make a null value. Basically:
+ //
+ // public static String returnNull() { return null; }
+ MethodBuilder returnNull{cbuilder.CreateMethod("returnNull", Prototype{string_type})};
+ [](MethodBuilder& method) {
+ Value zero = method.MakeRegister();
+ method.BuildConst4(zero, 0);
+ method.BuildReturn(zero, /*is_object=*/true);
+ }(returnNull);
+ returnNull.Encode();
+
+ // Test that we can make String literals. Basically:
+ //
+ // public static String makeString() { return "Hello, World!"; }
+ MethodBuilder makeString{cbuilder.CreateMethod("makeString", Prototype{string_type})};
+ [](MethodBuilder& method) {
+ Value string = method.MakeRegister();
+ method.BuildConstString(string, "Hello, World!");
+ method.BuildReturn(string, /*is_object=*/true);
+ }(makeString);
+ makeString.Encode();
+
+ // Make sure strings are sorted correctly.
+ //
+ // int returnStringIfZeroAB(int x) { if (x == 0) { return "a"; } else { return "b"; } }
+ MethodBuilder returnStringIfZeroAB{
+ cbuilder.CreateMethod("returnStringIfZeroAB", Prototype{string_type, TypeDescriptor::Int()})};
+ [&](MethodBuilder& method) {
+ Value resultIfZero{method.MakeRegister()};
+ Value else_target{method.MakeLabel()};
+ method.AddInstruction(Instruction::OpWithArgs(
+ Instruction::Op::kBranchEqz, /*dest=*/{}, Value::Parameter(0), else_target));
+ // else branch
+ method.BuildConstString(resultIfZero, "b");
+ method.AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+ // then branch
+ method.AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kBindLabel, /*dest=*/{}, else_target));
+ method.BuildConstString(resultIfZero, "a");
+ method.AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+ method.Encode();
+ }(returnStringIfZeroAB);
+ // int returnStringIfZeroAB(int x) { if (x == 0) { return "b"; } else { return "a"; } }
+ MethodBuilder returnStringIfZeroBA{
+ cbuilder.CreateMethod("returnStringIfZeroBA", Prototype{string_type, TypeDescriptor::Int()})};
+ [&](MethodBuilder& method) {
+ Value resultIfZero{method.MakeRegister()};
+ Value else_target{method.MakeLabel()};
+ method.AddInstruction(Instruction::OpWithArgs(
+ Instruction::Op::kBranchEqz, /*dest=*/{}, Value::Parameter(0), else_target));
+ // else branch
+ method.BuildConstString(resultIfZero, "a");
+ method.AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+ // then branch
+ method.AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kBindLabel, /*dest=*/{}, else_target));
+ method.BuildConstString(resultIfZero, "b");
+ method.AddInstruction(
+ Instruction::OpWithArgs(Instruction::Op::kReturnObject, /*dest=*/{}, resultIfZero));
+ method.Encode();
+ }(returnStringIfZeroBA);
+
slicer::MemView image{dex_file.CreateImage()};
std::ofstream out_file(outdir + "/simple.dex");
out_file.write(image.ptr<const char>(), image.size());
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index fbc54ae6a857..b74477043893 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1320,18 +1320,13 @@ public class CarrierConfigManager {
public static final String KEY_MMS_CLOSE_CONNECTION_BOOL = "mmsCloseConnection";
/**
- * If carriers require differentiate un-provisioned status: cold sim or out of credit sim
- * a package name and activity name can be provided to launch a supported carrier application
- * that check the sim provisioning status
- * The first element is the package name and the second element is the activity name
- * of the provisioning app
- * example:
- * <item>com.google.android.carrierPackageName</item>
- * <item>com.google.android.carrierPackageName.CarrierActivityName</item>
- * The ComponentName of the carrier activity that can setup the device and activate with the
- * network as part of the Setup Wizard flow.
+ * The flatten {@link android.content.ComponentName componentName} of the activity that can
+ * setup the device and activate with the network per carrier requirements.
+ *
+ * e.g, com.google.android.carrierPackageName/.CarrierActivityName
* @hide
*/
+ @SystemApi
public static final String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string";
/**
diff --git a/telephony/java/android/telephony/CellConfigLte.java b/telephony/java/android/telephony/CellConfigLte.java
new file mode 100644
index 000000000000..35769f04c5ae
--- /dev/null
+++ b/telephony/java/android/telephony/CellConfigLte.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * The container of LTE cell related configs.
+ * @hide
+ */
+public class CellConfigLte implements Parcelable {
+ private final boolean mIsEndcAvailable;
+
+ /** @hide */
+ public CellConfigLte() {
+ mIsEndcAvailable = false;
+ }
+
+ /** @hide */
+ public CellConfigLte(boolean isEndcAvailable) {
+ mIsEndcAvailable = isEndcAvailable;
+ }
+
+ /** @hide */
+ public CellConfigLte(CellConfigLte config) {
+ mIsEndcAvailable = config.mIsEndcAvailable;
+ }
+
+ /**
+ * Indicates that if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the LTE cell.
+ *
+ * Reference: 3GPP TS 36.331 v15.2.2 6.3.1 System information blocks.
+ *
+ * @return {@code true} if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the LTE cell.
+ *
+ */
+ boolean isEndcAvailable() {
+ return mIsEndcAvailable;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mIsEndcAvailable);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof CellConfigLte)) return false;
+
+ CellConfigLte o = (CellConfigLte) other;
+ return mIsEndcAvailable == o.mIsEndcAvailable;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeBoolean(mIsEndcAvailable);
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder().append(this.getClass().getName())
+ .append(" :{")
+ .append(" isEndcAvailable = " + mIsEndcAvailable)
+ .append(" }")
+ .toString();
+ }
+
+ private CellConfigLte(Parcel in) {
+ mIsEndcAvailable = in.readBoolean();
+ }
+
+ public static final Creator<CellConfigLte> CREATOR = new Creator<CellConfigLte>() {
+ @Override
+ public CellConfigLte createFromParcel(Parcel in) {
+ return new CellConfigLte(in);
+ }
+
+ @Override
+ public CellConfigLte[] newArray(int size) {
+ return new CellConfigLte[0];
+ }
+ };
+}
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index 389f643e05a4..7d5388b7b7f4 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -19,7 +19,8 @@ package android.telephony;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Rlog;
+
+import java.util.Objects;
/**
* A {@link CellInfo} representing an LTE cell that provides identity and measurement info.
@@ -31,6 +32,7 @@ public final class CellInfoLte extends CellInfo implements Parcelable {
private CellIdentityLte mCellIdentityLte;
private CellSignalStrengthLte mCellSignalStrengthLte;
+ private CellConfigLte mCellConfig;
/** @hide */
@UnsupportedAppUsage
@@ -38,6 +40,7 @@ public final class CellInfoLte extends CellInfo implements Parcelable {
super();
mCellIdentityLte = new CellIdentityLte();
mCellSignalStrengthLte = new CellSignalStrengthLte();
+ mCellConfig = new CellConfigLte();
}
/** @hide */
@@ -45,6 +48,7 @@ public final class CellInfoLte extends CellInfo implements Parcelable {
super(ci);
this.mCellIdentityLte = ci.mCellIdentityLte.copy();
this.mCellSignalStrengthLte = ci.mCellSignalStrengthLte.copy();
+ this.mCellConfig = new CellConfigLte(ci.mCellConfig);
}
@Override
@@ -71,26 +75,37 @@ public final class CellInfoLte extends CellInfo implements Parcelable {
mCellSignalStrengthLte = css;
}
+ /** @hide */
+ public void setCellConfig(CellConfigLte cellConfig) {
+ if (DBG) log("setCellConfig: " + cellConfig);
+ mCellConfig = cellConfig;
+ }
+
+ /** @hide */
+ public CellConfigLte getCellConfig() {
+ if (DBG) log("getCellConfig: " + mCellConfig);
+ return mCellConfig;
+ }
+
/**
* @return hash code
*/
@Override
public int hashCode() {
- return super.hashCode() + mCellIdentityLte.hashCode() + mCellSignalStrengthLte.hashCode();
+ return Objects.hash(
+ super.hashCode(),
+ mCellIdentityLte.hashCode(),
+ mCellSignalStrengthLte.hashCode(),
+ mCellConfig.hashCode());
}
@Override
public boolean equals(Object other) {
- if (!super.equals(other)) {
- return false;
- }
- try {
- CellInfoLte o = (CellInfoLte) other;
- return mCellIdentityLte.equals(o.mCellIdentityLte)
- && mCellSignalStrengthLte.equals(o.mCellSignalStrengthLte);
- } catch (ClassCastException e) {
- return false;
- }
+ if (!(other instanceof CellInfoLte)) return false;
+ CellInfoLte o = (CellInfoLte) other;
+ return super.equals(o) && mCellIdentityLte.equals(o.mCellIdentityLte)
+ && mCellSignalStrengthLte.equals(o.mCellSignalStrengthLte)
+ && mCellConfig.equals(o.mCellConfig);
}
@Override
@@ -101,6 +116,7 @@ public final class CellInfoLte extends CellInfo implements Parcelable {
sb.append(super.toString());
sb.append(" ").append(mCellIdentityLte);
sb.append(" ").append(mCellSignalStrengthLte);
+ sb.append(" ").append(mCellConfig);
sb.append("}");
return sb.toString();
@@ -119,6 +135,7 @@ public final class CellInfoLte extends CellInfo implements Parcelable {
super.writeToParcel(dest, flags, TYPE_LTE);
mCellIdentityLte.writeToParcel(dest, flags);
mCellSignalStrengthLte.writeToParcel(dest, flags);
+ mCellConfig.writeToParcel(dest, flags);
}
/**
@@ -129,6 +146,7 @@ public final class CellInfoLte extends CellInfo implements Parcelable {
super(in);
mCellIdentityLte = CellIdentityLte.CREATOR.createFromParcel(in);
mCellSignalStrengthLte = CellSignalStrengthLte.CREATOR.createFromParcel(in);
+ mCellConfig = CellConfigLte.CREATOR.createFromParcel(in);
if (DBG) log("CellInfoLte(Parcel): " + toString());
}
diff --git a/telephony/java/android/telephony/DataSpecificRegistrationStates.java b/telephony/java/android/telephony/DataSpecificRegistrationStates.java
index 97e3037b3c90..b6e6cbae8c26 100644
--- a/telephony/java/android/telephony/DataSpecificRegistrationStates.java
+++ b/telephony/java/android/telephony/DataSpecificRegistrationStates.java
@@ -17,17 +17,40 @@ public class DataSpecificRegistrationStates implements Parcelable{
*/
public final int maxDataCalls;
- DataSpecificRegistrationStates(int maxDataCalls) {
+ /**
+ * Indicates if the use of dual connectivity with NR is restricted.
+ * Reference: 3GPP TS 24.301 v15.03 section 9.3.3.12A.
+ */
+ public final boolean isDcNrRestricted;
+
+ /**
+ * Indicates if NR is supported by the selected PLMN.
+ *
+ * {@code true} if the bit N is in the PLMN-InfoList-r15 is true and the selected PLMN is
+ * present in plmn-IdentityList at position N.
+ * Reference: 3GPP TS 36.331 v15.2.2 section 6.3.1 PLMN-InfoList-r15.
+ * 3GPP TS 36.331 v15.2.2 section 6.2.2 SystemInformationBlockType1 message.
+ */
+ public final boolean isNrAvailable;
+
+ DataSpecificRegistrationStates(
+ int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable) {
this.maxDataCalls = maxDataCalls;
+ this.isDcNrRestricted = isDcNrRestricted;
+ this.isNrAvailable = isNrAvailable;
}
private DataSpecificRegistrationStates(Parcel source) {
maxDataCalls = source.readInt();
+ isDcNrRestricted = source.readBoolean();
+ isNrAvailable = source.readBoolean();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(maxDataCalls);
+ dest.writeBoolean(isDcNrRestricted);
+ dest.writeBoolean(isNrAvailable);
}
@Override
@@ -37,24 +60,30 @@ public class DataSpecificRegistrationStates implements Parcelable{
@Override
public String toString() {
- return "DataSpecificRegistrationStates {" + " mMaxDataCalls=" + maxDataCalls + "}";
+ return new StringBuilder().append(this.getClass().getName())
+ .append(" :{")
+ .append(" maxDataCalls = " + maxDataCalls)
+ .append(" isDcNrRestricted = " + isDcNrRestricted)
+ .append(" isNrAvailable = " + isNrAvailable)
+ .append(" }")
+ .toString();
}
@Override
public int hashCode() {
- return Objects.hash(maxDataCalls);
+ return Objects.hash(maxDataCalls, isDcNrRestricted, isNrAvailable);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || !(o instanceof DataSpecificRegistrationStates)) {
- return false;
- }
+ if (!(o instanceof DataSpecificRegistrationStates)) return false;
DataSpecificRegistrationStates other = (DataSpecificRegistrationStates) o;
- return this.maxDataCalls == other.maxDataCalls;
+ return this.maxDataCalls == other.maxDataCalls
+ && this.isDcNrRestricted == other.isDcNrRestricted
+ && this.isNrAvailable == other.isNrAvailable;
}
public static final Parcelable.Creator<DataSpecificRegistrationStates> CREATOR =
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java
index 68e512eaff37..aee744fac20c 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationState.java
@@ -70,6 +70,43 @@ public class NetworkRegistrationState implements Parcelable {
/** Registered on roaming network */
public static final int REG_STATE_ROAMING = 5;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "NR_STATUS_",
+ value = {NR_STATUS_NONE, NR_STATUS_RESTRICTED, NR_STATUS_NOT_RESTRICTED,
+ NR_STATUS_CONNECTED})
+ public @interface NRStatus {}
+
+ /**
+ * The device isn't camped on an LTE cell or the LTE cell doesn't support E-UTRA-NR
+ * Dual Connectivity(EN-DC).
+ * @hide
+ */
+ public static final int NR_STATUS_NONE = -1;
+
+ /**
+ * The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) but
+ * either the use of dual connectivity with NR(DCNR) is restricted or NR is not supported by
+ * the selected PLMN.
+ * @hide
+ */
+ public static final int NR_STATUS_RESTRICTED = 1;
+
+ /**
+ * The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) and both
+ * the use of dual connectivity with NR(DCNR) is not restricted and NR is supported by the
+ * selected PLMN.
+ * @hide
+ */
+ public static final int NR_STATUS_NOT_RESTRICTED = 2;
+
+ /**
+ * The device is camped on an LTE cell that supports E-UTRA-NR Dual Connectivity(EN-DC) and
+ * also connected to at least one 5G cell as a secondary serving cell.
+ * @hide
+ */
+ public static final int NR_STATUS_CONNECTED = 3;
+
/**
* Supported service type
* @hide
@@ -104,6 +141,9 @@ public class NetworkRegistrationState implements Parcelable {
private int mAccessNetworkTechnology;
+ @NRStatus
+ private int mNrStatus;
+
private final int mRejectCause;
private final boolean mEmergencyOnly;
@@ -154,6 +194,7 @@ public class NetworkRegistrationState implements Parcelable {
mAvailableServices = availableServices;
mCellIdentity = cellIdentity;
mEmergencyOnly = emergencyOnly;
+ mNrStatus = NR_STATUS_NONE;
}
/**
@@ -161,11 +202,9 @@ public class NetworkRegistrationState implements Parcelable {
* @hide
*/
public NetworkRegistrationState(int domain, int transportType, int regState,
- int accessNetworkTechnology, int rejectCause,
- boolean emergencyOnly, int[] availableServices,
- @Nullable CellIdentity cellIdentity, boolean cssSupported,
- int roamingIndicator, int systemIsInPrl,
- int defaultRoamingIndicator) {
+ int accessNetworkTechnology, int rejectCause, boolean emergencyOnly,
+ int[] availableServices, @Nullable CellIdentity cellIdentity, boolean cssSupported,
+ int roamingIndicator, int systemIsInPrl, int defaultRoamingIndicator) {
this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly,
availableServices, cellIdentity);
@@ -178,13 +217,14 @@ public class NetworkRegistrationState implements Parcelable {
* @hide
*/
public NetworkRegistrationState(int domain, int transportType, int regState,
- int accessNetworkTechnology, int rejectCause,
- boolean emergencyOnly, int[] availableServices,
- @Nullable CellIdentity cellIdentity, int maxDataCalls) {
+ int accessNetworkTechnology, int rejectCause, boolean emergencyOnly,
+ int[] availableServices, @Nullable CellIdentity cellIdentity, int maxDataCalls,
+ boolean isDcNrRestricted, boolean isNrAvailable) {
this(domain, transportType, regState, accessNetworkTechnology, rejectCause, emergencyOnly,
availableServices, cellIdentity);
- mDataSpecificStates = new DataSpecificRegistrationStates(maxDataCalls);
+ mDataSpecificStates = new DataSpecificRegistrationStates(
+ maxDataCalls, isDcNrRestricted, isNrAvailable);
}
protected NetworkRegistrationState(Parcel source) {
@@ -201,6 +241,7 @@ public class NetworkRegistrationState implements Parcelable {
VoiceSpecificRegistrationStates.class.getClassLoader());
mDataSpecificStates = source.readParcelable(
DataSpecificRegistrationStates.class.getClassLoader());
+ mNrStatus = source.readInt();
}
/**
@@ -214,6 +255,19 @@ public class NetworkRegistrationState implements Parcelable {
public @Domain int getDomain() { return mDomain; }
/**
+ * @return the 5G NR connection status.
+ * @hide
+ */
+ public @NRStatus int getNrStatus() {
+ return mNrStatus;
+ }
+
+ /** @hide */
+ public void setNrStatus(@NRStatus int nrStatus) {
+ mNrStatus = nrStatus;
+ }
+
+ /**
* @return The registration state.
*/
public @RegState int getRegState() {
@@ -316,6 +370,19 @@ public class NetworkRegistrationState implements Parcelable {
return "Unknown reg state " + regState;
}
+ private static String nrStatusToString(@NRStatus int nrStatus) {
+ switch (nrStatus) {
+ case NR_STATUS_RESTRICTED:
+ return "RESTRICTED";
+ case NR_STATUS_NOT_RESTRICTED:
+ return "NOT_RESTRICTED";
+ case NR_STATUS_CONNECTED:
+ return "CONNECTED";
+ default:
+ return "NONE";
+ }
+ }
+
@Override
public String toString() {
return new StringBuilder("NetworkRegistrationState{")
@@ -331,6 +398,7 @@ public class NetworkRegistrationState implements Parcelable {
.append(" cellIdentity=").append(mCellIdentity)
.append(" voiceSpecificStates=").append(mVoiceSpecificStates)
.append(" dataSpecificStates=").append(mDataSpecificStates)
+ .append(" nrStatus=").append(nrStatusToString(mNrStatus))
.append("}").toString();
}
@@ -338,14 +406,14 @@ public class NetworkRegistrationState implements Parcelable {
public int hashCode() {
return Objects.hash(mDomain, mTransportType, mRegState, mRoamingType,
mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
- mCellIdentity, mVoiceSpecificStates, mDataSpecificStates);
+ mCellIdentity, mVoiceSpecificStates, mDataSpecificStates, mNrStatus);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || !(o instanceof NetworkRegistrationState)) {
+ if (!(o instanceof NetworkRegistrationState)) {
return false;
}
@@ -357,11 +425,11 @@ public class NetworkRegistrationState implements Parcelable {
&& mAccessNetworkTechnology == other.mAccessNetworkTechnology
&& mRejectCause == other.mRejectCause
&& mEmergencyOnly == other.mEmergencyOnly
- && (mAvailableServices == other.mAvailableServices
- || Arrays.equals(mAvailableServices, other.mAvailableServices))
- && equals(mCellIdentity, other.mCellIdentity)
- && equals(mVoiceSpecificStates, other.mVoiceSpecificStates)
- && equals(mDataSpecificStates, other.mDataSpecificStates);
+ && Arrays.equals(mAvailableServices, other.mAvailableServices)
+ && Objects.equals(mCellIdentity, other.mCellIdentity)
+ && Objects.equals(mVoiceSpecificStates, other.mVoiceSpecificStates)
+ && Objects.equals(mDataSpecificStates, other.mDataSpecificStates)
+ && mNrStatus == other.mNrStatus;
}
@Override
@@ -377,6 +445,7 @@ public class NetworkRegistrationState implements Parcelable {
dest.writeParcelable(mCellIdentity, 0);
dest.writeParcelable(mVoiceSpecificStates, 0);
dest.writeParcelable(mDataSpecificStates, 0);
+ dest.writeInt(mNrStatus);
}
public static final Parcelable.Creator<NetworkRegistrationState> CREATOR =
@@ -391,14 +460,4 @@ public class NetworkRegistrationState implements Parcelable {
return new NetworkRegistrationState[size];
}
};
-
- private static boolean equals(Object o1, Object o2) {
- if (o1 == o2) {
- return true;
- } else if (o1 == null) {
- return false;
- } else {
- return o1.equals(o2);
- }
- }
}
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index f5dff20eedf2..3c5ad84a62b0 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -21,16 +21,18 @@ import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.Looper;
-import android.os.Message;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.IPhoneStateListener;
import java.lang.ref.WeakReference;
import java.util.List;
+import java.util.concurrent.Executor;
/**
* A listener class for monitoring changes in specific telephony states
@@ -231,34 +233,35 @@ public class PhoneStateListener {
public static final int LISTEN_CARRIER_NETWORK_CHANGE = 0x00010000;
/**
- * Listen for changes to the sim voice activation state
- * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
- * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
- * {@more}
- * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates voice service has been
- * fully activated
+ * Listen for changes to the sim voice activation state
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
+ * {@more}
+ * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates voice service has been
+ * fully activated
*
- * @see #onVoiceActivationStateChanged
- * @hide
+ * @see #onVoiceActivationStateChanged
+ * @hide
*/
+ @SystemApi
public static final int LISTEN_VOICE_ACTIVATION_STATE = 0x00020000;
/**
- * Listen for changes to the sim data activation state
- * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
- * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
- * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
- * {@more}
- * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates data service has been
- * fully activated
+ * Listen for changes to the sim data activation state
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
+ * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
+ * {@more}
+ * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates data service has been
+ * fully activated
*
- * @see #onDataActivationStateChanged
- * @hide
+ * @see #onDataActivationStateChanged
+ * @hide
*/
public static final int LISTEN_DATA_ACTIVATION_STATE = 0x00040000;
@@ -320,7 +323,12 @@ public class PhoneStateListener {
@UnsupportedAppUsage
protected Integer mSubId;
- private final Handler mHandler;
+ /**
+ * @hide
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ @UnsupportedAppUsage
+ public final IPhoneStateListener callback;
/**
* Create a PhoneStateListener for the Phone with the default subscription.
@@ -358,95 +366,27 @@ public class PhoneStateListener {
*/
@UnsupportedAppUsage
public PhoneStateListener(Integer subId, Looper looper) {
- if (DBG) log("ctor: subId=" + subId + " looper=" + looper);
+ this(subId, new HandlerExecutor(new Handler(looper)));
+ }
+
+ /**
+ * Create a PhoneStateListener for the Phone using the specified Executor
+ *
+ * <p>Create a PhoneStateListener with a specified Executor for handling necessary callbacks.
+ * The Executor must not be null.
+ *
+ * @param executor a non-null Executor that will execute callbacks for the PhoneStateListener.
+ */
+ public PhoneStateListener(@NonNull Executor executor) {
+ this(null, executor);
+ }
+
+ private PhoneStateListener(Integer subId, Executor e) {
+ if (e == null) {
+ throw new IllegalArgumentException("PhoneStateListener Executor must be non-null");
+ }
mSubId = subId;
- mHandler = new Handler(looper) {
- public void handleMessage(Message msg) {
- if (DBG) {
- log("mSubId=" + mSubId + " what=0x" + Integer.toHexString(msg.what)
- + " msg=" + msg);
- }
- switch (msg.what) {
- case LISTEN_SERVICE_STATE:
- PhoneStateListener.this.onServiceStateChanged((ServiceState)msg.obj);
- break;
- case LISTEN_SIGNAL_STRENGTH:
- PhoneStateListener.this.onSignalStrengthChanged(msg.arg1);
- break;
- case LISTEN_MESSAGE_WAITING_INDICATOR:
- PhoneStateListener.this.onMessageWaitingIndicatorChanged(msg.arg1 != 0);
- break;
- case LISTEN_CALL_FORWARDING_INDICATOR:
- PhoneStateListener.this.onCallForwardingIndicatorChanged(msg.arg1 != 0);
- break;
- case LISTEN_CELL_LOCATION:
- PhoneStateListener.this.onCellLocationChanged((CellLocation)msg.obj);
- break;
- case LISTEN_CALL_STATE:
- PhoneStateListener.this.onCallStateChanged(msg.arg1, (String)msg.obj);
- break;
- case LISTEN_DATA_CONNECTION_STATE:
- PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1, msg.arg2);
- PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1);
- break;
- case LISTEN_DATA_ACTIVITY:
- PhoneStateListener.this.onDataActivity(msg.arg1);
- break;
- case LISTEN_SIGNAL_STRENGTHS:
- PhoneStateListener.this.onSignalStrengthsChanged((SignalStrength)msg.obj);
- break;
- case LISTEN_OTASP_CHANGED:
- PhoneStateListener.this.onOtaspChanged(msg.arg1);
- break;
- case LISTEN_CELL_INFO:
- PhoneStateListener.this.onCellInfoChanged((List<CellInfo>)msg.obj);
- break;
- case LISTEN_PRECISE_CALL_STATE:
- PhoneStateListener.this.onPreciseCallStateChanged((PreciseCallState)msg.obj);
- break;
- case LISTEN_PRECISE_DATA_CONNECTION_STATE:
- PhoneStateListener.this.onPreciseDataConnectionStateChanged(
- (PreciseDataConnectionState)msg.obj);
- break;
- case LISTEN_DATA_CONNECTION_REAL_TIME_INFO:
- PhoneStateListener.this.onDataConnectionRealTimeInfoChanged(
- (DataConnectionRealTimeInfo)msg.obj);
- break;
- case LISTEN_SRVCC_STATE_CHANGED:
- PhoneStateListener.this.onSrvccStateChanged((int) msg.obj);
- break;
- case LISTEN_VOICE_ACTIVATION_STATE:
- PhoneStateListener.this.onVoiceActivationStateChanged((int)msg.obj);
- break;
- case LISTEN_DATA_ACTIVATION_STATE:
- PhoneStateListener.this.onDataActivationStateChanged((int)msg.obj);
- break;
- case LISTEN_USER_MOBILE_DATA_STATE:
- PhoneStateListener.this.onUserMobileDataStateChanged((boolean)msg.obj);
- break;
- case LISTEN_OEM_HOOK_RAW_EVENT:
- PhoneStateListener.this.onOemHookRawEvent((byte[])msg.obj);
- break;
- case LISTEN_CARRIER_NETWORK_CHANGE:
- PhoneStateListener.this.onCarrierNetworkChange((boolean)msg.obj);
- break;
- case LISTEN_PHYSICAL_CHANNEL_CONFIGURATION:
- PhoneStateListener.this.onPhysicalChannelConfigurationChanged(
- (List<PhysicalChannelConfig>)msg.obj);
- break;
- case LISTEN_PHONE_CAPABILITY_CHANGE:
- PhoneStateListener.this.onPhoneCapabilityChanged(
- (PhoneCapability) msg.obj);
- break;
- case LISTEN_PREFERRED_DATA_SUBID_CHANGE:
- PhoneStateListener.this.onPreferredDataSubIdChanged((int) msg.obj);
- break;
- case LISTEN_RADIO_POWER_STATE_CHANGED:
- PhoneStateListener.this.onRadioPowerStateChanged((int) msg.obj);
- break;
- }
- }
- };
+ callback = new IPhoneStateListenerStub(this, e);
}
/**
@@ -630,8 +570,8 @@ public class PhoneStateListener {
* @param state is the current SIM voice activation state
* @hide
*/
- public void onVoiceActivationStateChanged(int state) {
-
+ @SystemApi
+ public void onVoiceActivationStateChanged(@TelephonyManager.SimActivationState int state) {
}
/**
@@ -639,8 +579,7 @@ public class PhoneStateListener {
* @param state is the current SIM data activation state
* @hide
*/
- public void onDataActivationStateChanged(int state) {
-
+ public void onDataActivationStateChanged(@TelephonyManager.SimActivationState int state) {
}
/**
@@ -735,127 +674,217 @@ public class PhoneStateListener {
*/
private static class IPhoneStateListenerStub extends IPhoneStateListener.Stub {
private WeakReference<PhoneStateListener> mPhoneStateListenerWeakRef;
+ private Executor mExecutor;
- public IPhoneStateListenerStub(PhoneStateListener phoneStateListener) {
+ IPhoneStateListenerStub(PhoneStateListener phoneStateListener, Executor executor) {
mPhoneStateListenerWeakRef = new WeakReference<PhoneStateListener>(phoneStateListener);
- }
-
- private void send(int what, int arg1, int arg2, Object obj) {
- PhoneStateListener listener = mPhoneStateListenerWeakRef.get();
- if (listener != null) {
- Message.obtain(listener.mHandler, what, arg1, arg2, obj).sendToTarget();
- }
+ mExecutor = executor;
}
public void onServiceStateChanged(ServiceState serviceState) {
- send(LISTEN_SERVICE_STATE, 0, 0, serviceState);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onServiceStateChanged(serviceState)));
}
public void onSignalStrengthChanged(int asu) {
- send(LISTEN_SIGNAL_STRENGTH, asu, 0, null);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onSignalStrengthChanged(asu)));
}
public void onMessageWaitingIndicatorChanged(boolean mwi) {
- send(LISTEN_MESSAGE_WAITING_INDICATOR, mwi ? 1 : 0, 0, null);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onMessageWaitingIndicatorChanged(mwi)));
}
public void onCallForwardingIndicatorChanged(boolean cfi) {
- send(LISTEN_CALL_FORWARDING_INDICATOR, cfi ? 1 : 0, 0, null);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onCallForwardingIndicatorChanged(cfi)));
}
public void onCellLocationChanged(Bundle bundle) {
CellLocation location = CellLocation.newFromBundle(bundle);
- send(LISTEN_CELL_LOCATION, 0, 0, location);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onCellLocationChanged(location)));
}
public void onCallStateChanged(int state, String incomingNumber) {
- send(LISTEN_CALL_STATE, state, 0, incomingNumber);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onCallStateChanged(state, incomingNumber)));
}
public void onDataConnectionStateChanged(int state, int networkType) {
- send(LISTEN_DATA_CONNECTION_STATE, state, networkType, null);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onDataConnectionStateChanged(state, networkType)));
}
public void onDataActivity(int direction) {
- send(LISTEN_DATA_ACTIVITY, direction, 0, null);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onDataActivity(direction)));
}
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
- send(LISTEN_SIGNAL_STRENGTHS, 0, 0, signalStrength);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onSignalStrengthsChanged(signalStrength)));
}
public void onOtaspChanged(int otaspMode) {
- send(LISTEN_OTASP_CHANGED, otaspMode, 0, null);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onOtaspChanged(otaspMode)));
}
public void onCellInfoChanged(List<CellInfo> cellInfo) {
- send(LISTEN_CELL_INFO, 0, 0, cellInfo);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onCellInfoChanged(cellInfo)));
}
public void onPreciseCallStateChanged(PreciseCallState callState) {
- send(LISTEN_PRECISE_CALL_STATE, 0, 0, callState);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onPreciseCallStateChanged(callState)));
}
public void onPreciseDataConnectionStateChanged(
PreciseDataConnectionState dataConnectionState) {
- send(LISTEN_PRECISE_DATA_CONNECTION_STATE, 0, 0, dataConnectionState);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onPreciseDataConnectionStateChanged(dataConnectionState)));
}
- public void onDataConnectionRealTimeInfoChanged(
- DataConnectionRealTimeInfo dcRtInfo) {
- send(LISTEN_DATA_CONNECTION_REAL_TIME_INFO, 0, 0, dcRtInfo);
+ public void onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo dcRtInfo) {
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onDataConnectionRealTimeInfoChanged(dcRtInfo)));
}
public void onSrvccStateChanged(int state) {
- send(LISTEN_SRVCC_STATE_CHANGED, 0, 0, state);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onSrvccStateChanged(state)));
}
public void onVoiceActivationStateChanged(int activationState) {
- send(LISTEN_VOICE_ACTIVATION_STATE, 0, 0, activationState);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onVoiceActivationStateChanged(activationState)));
}
public void onDataActivationStateChanged(int activationState) {
- send(LISTEN_DATA_ACTIVATION_STATE, 0, 0, activationState);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onDataActivationStateChanged(activationState)));
}
public void onUserMobileDataStateChanged(boolean enabled) {
- send(LISTEN_USER_MOBILE_DATA_STATE, 0, 0, enabled);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onUserMobileDataStateChanged(enabled)));
}
public void onOemHookRawEvent(byte[] rawData) {
- send(LISTEN_OEM_HOOK_RAW_EVENT, 0, 0, rawData);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onOemHookRawEvent(rawData)));
}
public void onCarrierNetworkChange(boolean active) {
- send(LISTEN_CARRIER_NETWORK_CHANGE, 0, 0, active);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onCarrierNetworkChange(active)));
}
public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) {
- send(LISTEN_PHYSICAL_CHANNEL_CONFIGURATION, 0, 0, configs);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(
+ () -> psl.onPhysicalChannelConfigurationChanged(configs)));
}
public void onPhoneCapabilityChanged(PhoneCapability capability) {
- send(LISTEN_PHONE_CAPABILITY_CHANGE, 0, 0, capability);
- }
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
- public void onPreferredDataSubIdChanged(int subId) {
- send(LISTEN_PREFERRED_DATA_SUBID_CHANGE, 0, 0, subId);
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onPhoneCapabilityChanged(capability)));
}
public void onRadioPowerStateChanged(@TelephonyManager.RadioPowerState int state) {
- send(LISTEN_RADIO_POWER_STATE_CHANGED, 0, 0, state);
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onRadioPowerStateChanged(state)));
}
+ public void onPreferredDataSubIdChanged(int subId) {
+ PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
+ if (psl == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> psl.onPreferredDataSubIdChanged(subId)));
+ }
}
- /**
- * @hide
- */
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- @UnsupportedAppUsage
- public final IPhoneStateListener callback = new IPhoneStateListenerStub(this);
private void log(String s) {
Rlog.d(LOG_TAG, s);
}
-} \ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 0937b1071e23..ab80e252c03d 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -83,7 +83,45 @@ public class ServiceState implements Parcelable {
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef({DUPLEX_MODE_UNKNOWN, DUPLEX_MODE_FDD, DUPLEX_MODE_TDD})
+ @IntDef(prefix = "FREQUENCY_RANGE_",
+ value = {FREQUENCY_RANGE_UNKNOWN, FREQUENCY_RANGE_LOW, FREQUENCY_RANGE_MID,
+ FREQUENCY_RANGE_HIGH, FREQUENCY_RANGE_MMWAVE})
+ public @interface FrequencyRange {}
+
+ /**
+ * Indicates frequency range is unknown.
+ * @hide
+ */
+ public static final int FREQUENCY_RANGE_UNKNOWN = -1;
+
+ /**
+ * Indicates the frequency range is below 1GHz.
+ * @hide
+ */
+ public static final int FREQUENCY_RANGE_LOW = 1;
+
+ /**
+ * Indicates the frequency range is between 1GHz to 3GHz.
+ * @hide
+ */
+ public static final int FREQUENCY_RANGE_MID = 2;
+
+ /**
+ * Indicates the frequency range is between 3GHz and 6GHz.
+ * @hide
+ */
+ public static final int FREQUENCY_RANGE_HIGH = 3;
+
+ /**
+ * Indicates the frequency range is above 6GHz (millimeter wave frequency).
+ * @hide
+ */
+ public static final int FREQUENCY_RANGE_MMWAVE = 4;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "DUPLEX_MODE_",
+ value = {DUPLEX_MODE_UNKNOWN, DUPLEX_MODE_FDD, DUPLEX_MODE_TDD})
public @interface DuplexMode {}
/**
@@ -283,6 +321,8 @@ public class ServiceState implements Parcelable {
@UnsupportedAppUsage
private boolean mIsUsingCarrierAggregation;
+ @FrequencyRange
+ private int mNrFrequencyRange;
private int mChannelNumber;
private int[] mCellBandwidths = new int[0];
@@ -375,6 +415,7 @@ public class ServiceState implements Parcelable {
mLteEarfcnRsrpBoost = s.mLteEarfcnRsrpBoost;
mNetworkRegistrationStates = s.mNetworkRegistrationStates == null ? null :
new ArrayList<>(s.mNetworkRegistrationStates);
+ mNrFrequencyRange = s.mNrFrequencyRange;
}
/**
@@ -406,6 +447,7 @@ public class ServiceState implements Parcelable {
in.readList(mNetworkRegistrationStates, NetworkRegistrationState.class.getClassLoader());
mChannelNumber = in.readInt();
mCellBandwidths = in.createIntArray();
+ mNrFrequencyRange = in.readInt();
}
public void writeToParcel(Parcel out, int flags) {
@@ -433,6 +475,7 @@ public class ServiceState implements Parcelable {
out.writeList(mNetworkRegistrationStates);
out.writeInt(mChannelNumber);
out.writeIntArray(mCellBandwidths);
+ out.writeInt(mNrFrequencyRange);
}
public int describeContents() {
@@ -792,7 +835,8 @@ public class ServiceState implements Parcelable {
mIsEmergencyOnly,
mIsUsingCarrierAggregation,
mLteEarfcnRsrpBoost,
- mNetworkRegistrationStates);
+ mNetworkRegistrationStates,
+ mNrFrequencyRange);
}
@Override
@@ -823,7 +867,8 @@ public class ServiceState implements Parcelable {
&& mIsUsingCarrierAggregation == s.mIsUsingCarrierAggregation)
&& (mNetworkRegistrationStates == null ? s.mNetworkRegistrationStates == null :
s.mNetworkRegistrationStates != null &&
- mNetworkRegistrationStates.containsAll(s.mNetworkRegistrationStates));
+ mNetworkRegistrationStates.containsAll(s.mNetworkRegistrationStates))
+ && mNrFrequencyRange == s.mNrFrequencyRange;
}
/**
@@ -958,6 +1003,7 @@ public class ServiceState implements Parcelable {
.append(", mIsUsingCarrierAggregation=").append(mIsUsingCarrierAggregation)
.append(", mLteEarfcnRsrpBoost=").append(mLteEarfcnRsrpBoost)
.append(", mNetworkRegistrationStates=").append(mNetworkRegistrationStates)
+ .append(", mNrFrequencyRange=").append(mNrFrequencyRange)
.append("}").toString();
}
@@ -987,6 +1033,7 @@ public class ServiceState implements Parcelable {
mIsUsingCarrierAggregation = false;
mLteEarfcnRsrpBoost = 0;
mNetworkRegistrationStates = new ArrayList<>();
+ mNrFrequencyRange = FREQUENCY_RANGE_UNKNOWN;
}
public void setStateOutOfService() {
@@ -1225,6 +1272,7 @@ public class ServiceState implements Parcelable {
m.putInt("LteEarfcnRsrpBoost", mLteEarfcnRsrpBoost);
m.putInt("ChannelNumber", mChannelNumber);
m.putIntArray("CellBandwidths", mCellBandwidths);
+ m.putInt("mNrFrequencyRange", mNrFrequencyRange);
}
/** @hide */
@@ -1288,6 +1336,22 @@ public class ServiceState implements Parcelable {
mIsUsingCarrierAggregation = ca;
}
+ /**
+ * @return the frequency range of 5G NR.
+ * @hide
+ */
+ public @FrequencyRange int getNrFrequencyRange() {
+ return mNrFrequencyRange;
+ }
+
+ /**
+ * @param nrFrequencyRange the frequency range of 5G NR.
+ * @hide
+ */
+ public void setNrFrequencyRange(@FrequencyRange int nrFrequencyRange) {
+ mNrFrequencyRange = nrFrequencyRange;
+ }
+
/** @hide */
public int getLteEarfcnRsrpBoost() {
return mLteEarfcnRsrpBoost;
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 22c1e58449de..b41e14e09554 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -143,9 +143,11 @@ public class SubscriptionInfo implements Parcelable {
private boolean mIsOpportunistic;
/**
- * SubId of the parent subscription, if there is one.
+ * A UUID assigned to the subscription group. It returns
+ * null if not assigned.
*/
- private int mParentSubId;
+ @Nullable
+ private String mGroupUUID;
/**
* @hide
@@ -156,7 +158,7 @@ public class SubscriptionInfo implements Parcelable {
@Nullable UiccAccessRule[] accessRules, String cardId) {
this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
roaming, icon, mcc, mnc, countryIso, isEmbedded, accessRules, cardId,
- false, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ false, null);
}
/**
@@ -166,7 +168,7 @@ public class SubscriptionInfo implements Parcelable {
CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
@Nullable UiccAccessRule[] accessRules, String cardId, boolean isOpportunistic,
- int parentSubId) {
+ @Nullable String groupUUID) {
this.mId = id;
this.mIccId = iccId;
this.mSimSlotIndex = simSlotIndex;
@@ -184,7 +186,7 @@ public class SubscriptionInfo implements Parcelable {
this.mAccessRules = accessRules;
this.mCardId = cardId;
this.mIsOpportunistic = isOpportunistic;
- this.mParentSubId = parentSubId;
+ this.mGroupUUID = groupUUID;
}
/**
@@ -388,16 +390,16 @@ public class SubscriptionInfo implements Parcelable {
}
/**
- * Used in scenarios where a child subscription is bundled with a primary parent subscription.
- * The child subscription will typically be opportunistic (see {@link #isOpportunistic()})
- * and will be used to provide data services where available, with the parent being the primary
- * fallback subscription.
+ * Used in scenarios where different subscriptions are bundled as a group.
+ * It's typically a primary and an opportunistic subscription. (see {@link #isOpportunistic()})
+ * Such that those subscriptions will have some affiliated behaviors such as opportunistic
+ * subscription may be invisible to the user.
*
- * @return subId of parent subscription if it’s bundled with a primary subscription.
- * If there isn't one, {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}
+ * @return group UUID a String of group UUID if it belongs to a group. Otherwise
+ * it will return null.
*/
- public int getParentSubId() {
- return mParentSubId;
+ public String getGroupUuid() {
+ return mGroupUUID;
}
/**
@@ -493,11 +495,11 @@ public class SubscriptionInfo implements Parcelable {
UiccAccessRule[] accessRules = source.createTypedArray(UiccAccessRule.CREATOR);
String cardId = source.readString();
boolean isOpportunistic = source.readBoolean();
- int parentSubId = source.readInt();
+ String groupUUID = source.readString();
return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName,
nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso,
- isEmbedded, accessRules, cardId, isOpportunistic, parentSubId);
+ isEmbedded, accessRules, cardId, isOpportunistic, groupUUID);
}
@Override
@@ -525,7 +527,7 @@ public class SubscriptionInfo implements Parcelable {
dest.writeTypedArray(mAccessRules, flags);
dest.writeString(mCardId);
dest.writeBoolean(mIsOpportunistic);
- dest.writeInt(mParentSubId);
+ dest.writeString(mGroupUUID);
}
@Override
@@ -559,13 +561,13 @@ public class SubscriptionInfo implements Parcelable {
+ " mnc " + mMnc + "mCountryIso=" + mCountryIso + " isEmbedded " + mIsEmbedded
+ " accessRules " + Arrays.toString(mAccessRules)
+ " cardId=" + cardIdToPrint + " isOpportunistic " + mIsOpportunistic
- + " parentSubId=" + mParentSubId + "}";
+ + " mGroupUUID=" + mGroupUUID + "}";
}
@Override
public int hashCode() {
return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded,
- mIsOpportunistic, mParentSubId, mIccId, mNumber, mMcc, mMnc, mCountryIso,
+ mIsOpportunistic, mGroupUUID, mIccId, mNumber, mMcc, mMnc, mCountryIso,
mCardId, mDisplayName, mCarrierName, mAccessRules);
}
@@ -588,7 +590,7 @@ public class SubscriptionInfo implements Parcelable {
&& mDataRoaming == toCompare.mDataRoaming
&& mIsEmbedded == toCompare.mIsEmbedded
&& mIsOpportunistic == toCompare.mIsOpportunistic
- && mParentSubId == toCompare.mParentSubId
+ && Objects.equals(mGroupUUID, toCompare.mGroupUUID)
&& Objects.equals(mIccId, toCompare.mIccId)
&& Objects.equals(mNumber, toCompare.mNumber)
&& Objects.equals(mMcc, toCompare.mMcc)
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 31770ec1dce2..1dafc12e2ce0 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -119,7 +119,6 @@ public class SubscriptionManager {
@UnsupportedAppUsage
public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
-
/**
* Generates a content {@link Uri} used to receive updates on simInfo change
* on the given subscriptionId
@@ -577,6 +576,15 @@ public class SubscriptionManager {
public static final String PARENT_SUB_ID = "parent_sub_id";
/**
+ * TelephonyProvider column name for group ID. Subscriptions with same group ID
+ * are considered bundled together, and should behave as a single subscription at
+ * certain scenarios.
+ *
+ * @hide
+ */
+ public static final String GROUP_UUID = "group_uuid";
+
+ /**
* Broadcast Action: The user has changed one of the default subs related to
* data, phone calls, or sms</p>
*
@@ -2290,7 +2298,7 @@ public class SubscriptionManager {
* subscription dynamically in multi-SIM devices.
*
* @param subId which subscription is preferred to for cellular data. If it's
- * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}, it means
+ * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}, it means
* it's unset and {@link SubscriptionManager#getDefaultDataSubscriptionId()}
* is used to determine which modem is preferred.
* @hide
@@ -2365,19 +2373,40 @@ public class SubscriptionManager {
}
/**
- * Set parent subId by simInfo index
+ * Inform SubscriptionManager that subscriptions in the list are bundled
+ * as a group. Typically it's a primary subscription and an opportunistic
+ * subscription. It should only affect multi-SIM scenarios where primary
+ * and opportunistic subscriptions can be activated together.
+ * Being in the same group means they might be activated or deactivated
+ * together, some of them may be invisible to the users, etc.
*
- * @param parentSubId subId of its parent subscription.
- * @param subId the unique SubscriptionInfo index in database
- * @return the number of records updated
- * @hide
+ * Caller will either have {@link android.Manifest.permission.MODIFY_PHONE_STATE}
+ * permission or can manage all subscriptions in the list, according to their
+ * acess rules.
+ *
+ * @param subIdList list of subId that will be in the same group
+ * @return groupUUID a UUID assigned to the subscription group. It returns
+ * null if fails.
*
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
- public int setParentSubId(int parentSubId, int subId) {
- if (VDBG) logd("[setParentSubId]+ parentSubId:" + parentSubId + " subId:" + subId);
- return setSubscriptionPropertyHelper(subId, "parentSubId",
- (iSub)-> iSub.setParentSubId(parentSubId, subId));
+ public String setSubscriptionGroup(int[] subIdList) {
+ String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
+ if (VDBG) {
+ logd("[setSubscriptionGroup]+ subIdList:" + Arrays.toString(subIdList));
+ }
+
+ String groupUUID = null;
+ try {
+ ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+ if (iSub != null) {
+ groupUUID = iSub.setSubscriptionGroup(subIdList, pkgForDebug);
+ }
+ } catch (RemoteException ex) {
+ // ignore it
+ }
+
+ return groupUUID;
}
private interface CallISubMethodHelper {
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index c9cf473bb482..e06c3728836c 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -292,7 +292,7 @@ public class ImsMmTelManager {
* Create an instance of ImsManager for the subscription id specified.
*
* @param context
- * @param subId The ID of the subscription that this ImsManager will use.
+ * @param subId The ID of the subscription that this ImsMmTelManager will use.
* @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
* @throws IllegalArgumentException if the subscription is invalid or
* the subscription ID is not an active subscription.
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
new file mode 100644
index 000000000000..916e282f642e
--- /dev/null
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims;
+
+import android.Manifest;
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.ims.aidl.IImsConfigCallback;
+import android.telephony.ims.stub.ImsConfigImplBase;
+
+import com.android.internal.telephony.ITelephony;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Manages IMS provisioning and configuration parameters, as well as callbacks for apps to listen
+ * to changes in these configurations.
+ *
+ * Note: IMS provisioning keys are defined per carrier or OEM using OMA-DM or other provisioning
+ * applications and may vary.
+ * @hide
+ */
+@SystemApi
+public class ProvisioningManager {
+
+ /**
+ * Callback for IMS provisioning changes.
+ */
+ public static class Callback {
+
+ private static class CallbackBinder extends IImsConfigCallback.Stub {
+
+ private final Callback mLocalConfigurationCallback;
+ private Executor mExecutor;
+
+ private CallbackBinder(Callback localConfigurationCallback) {
+ mLocalConfigurationCallback = localConfigurationCallback;
+ }
+
+ @Override
+ public final void onIntConfigChanged(int item, int value) {
+ Binder.withCleanCallingIdentity(() ->
+ mExecutor.execute(() ->
+ mLocalConfigurationCallback.onProvisioningIntChanged(item, value)));
+ }
+
+ @Override
+ public final void onStringConfigChanged(int item, String value) {
+ Binder.withCleanCallingIdentity(() ->
+ mExecutor.execute(() ->
+ mLocalConfigurationCallback.onProvisioningStringChanged(item,
+ value)));
+ }
+
+ private void setExecutor(Executor executor) {
+ mExecutor = executor;
+ }
+ }
+
+ private final CallbackBinder mBinder = new CallbackBinder(this);
+
+ /**
+ * Called when a provisioning item has changed.
+ * @param item the IMS provisioning key constant, as defined by the OEM.
+ * @param value the new integer value of the IMS provisioning key.
+ */
+ public void onProvisioningIntChanged(int item, int value) {
+ // Base Implementation
+ }
+
+ /**
+ * Called when a provisioning item has changed.
+ * @param item the IMS provisioning key constant, as defined by the OEM.
+ * @param value the new String value of the IMS configuration constant.
+ */
+ public void onProvisioningStringChanged(int item, String value) {
+ // Base Implementation
+ }
+
+ /**@hide*/
+ public final IImsConfigCallback getBinder() {
+ return mBinder;
+ }
+
+ /**@hide*/
+ public void setExecutor(Executor executor) {
+ mBinder.setExecutor(executor);
+ }
+ }
+
+ private int mSubId;
+
+ /**
+ * Create a new {@link ProvisioningManager} for the subscription specified.
+ * @param context The context that this manager will use.
+ * @param subId The ID of the subscription that this ProvisioningManager will use.
+ * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
+ * @throws IllegalArgumentException if the subscription is invalid or
+ * the subscription ID is not an active subscription.
+ */
+ public static ProvisioningManager createForSubscriptionId(Context context, int subId) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)
+ || !getSubscriptionManager(context).isActiveSubscriptionId(subId)) {
+ throw new IllegalArgumentException("Invalid subscription ID");
+ }
+
+ return new ProvisioningManager(subId);
+ }
+
+ private ProvisioningManager(int subId) {
+ mSubId = subId;
+ }
+
+ /**
+ * Register a new {@link Callback} to listen to changes to changes in
+ * IMS provisioning. Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
+ * Subscription changed events and call
+ * {@link #unregisterProvisioningChangedCallback(Callback)} to clean up after a
+ * subscription is removed.
+ * @param executor The {@link Executor} to call the callback methods on
+ * @param callback The provisioning callbackto be registered.
+ * @see #unregisterProvisioningChangedCallback(Callback)
+ * @see SubscriptionManager.OnSubscriptionsChangedListener
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void registerProvisioningChangedCallback(@CallbackExecutor Executor executor,
+ @NonNull Callback callback) {
+ callback.setExecutor(executor);
+ try {
+ getITelephony().registerImsProvisioningChangedCallback(mSubId,
+ callback.getBinder());
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Unregister an existing {@link Callback}. Ensure to call this method when cleaning
+ * up to avoid memory leaks or when the subscription is removed.
+ * @param callback The existing {@link Callback} to be removed.
+ * @see #registerProvisioningChangedCallback(Executor, Callback)
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void unregisterProvisioningChangedCallback(@NonNull Callback callback) {
+ try {
+ getITelephony().unregisterImsProvisioningChangedCallback(mSubId,
+ callback.getBinder());
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Query for the integer value associated with the provided key.
+ * @param key An integer that represents the provisioning key, which is defined by the OEM.
+ * @return an integer value for the provided key.
+ * @throws IllegalArgumentException if the key provided was invalid.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public int getProvisioningIntValue(int key) {
+ try {
+ return getITelephony().getImsProvisioningInt(mSubId, key);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Query for the String value associated with the provided key.
+ * @param key An integer that represents the provisioning key, which is defined by the OEM.
+ * @return a String value for the provided key, or {@code null} if the key doesn't exist.
+ * @throws IllegalArgumentException if the key provided was invalid.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public String getProvisioningStringValue(int key) {
+ try {
+ return getITelephony().getImsProvisioningString(mSubId, key);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Set the integer value associated with the provided key.
+ * @param key An integer that represents the provisioning key, which is defined by the OEM.
+ * @param value a integer value for the provided key.
+ * @return the result of setting the configuration value.
+ */
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ public @ImsConfigImplBase.SetConfigResult int setProvisioningIntValue(int key, int value) {
+ try {
+ return getITelephony().setImsProvisioningInt(mSubId, key, value);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Set the String value associated with the provided key.
+ *
+ * @param key An integer that represents the provisioning key, which is defined by the OEM.
+ * @param value a String value for the provided key.
+ * @return the result of setting the configuration value.
+ */
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ public @ImsConfigImplBase.SetConfigResult int setProvisioningStringValue(int key,
+ String value) {
+ try {
+ return getITelephony().setImsProvisioningString(mSubId, key, value);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ private static SubscriptionManager getSubscriptionManager(Context context) {
+ SubscriptionManager manager = context.getSystemService(SubscriptionManager.class);
+ if (manager == null) {
+ throw new RuntimeException("Could not find SubscriptionManager.");
+ }
+ return manager;
+ }
+
+ private static ITelephony getITelephony() {
+ ITelephony binder = ITelephony.Stub.asInterface(
+ ServiceManager.getService(Context.TELEPHONY_SERVICE));
+ if (binder == null) {
+ throw new RuntimeException("Could not find Telephony Service.");
+ }
+ return binder;
+ }
+}
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index dcd7ea714f8c..321bfff40652 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -16,9 +16,9 @@
package android.telephony.ims.stub;
+import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.content.Context;
-import android.content.Intent;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.telephony.ims.aidl.IImsConfig;
@@ -28,6 +28,8 @@ import android.util.Log;
import com.android.ims.ImsConfig;
import com.android.internal.annotations.VisibleForTesting;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.HashMap;
@@ -215,41 +217,6 @@ public class ImsConfigImplBase {
}
/**
- * Callback that the framework uses for receiving Configuration change updates.
- * {@hide}
- */
- public static class Callback extends IImsConfigCallback.Stub {
-
- @Override
- public final void onIntConfigChanged(int item, int value) throws RemoteException {
- onConfigChanged(item, value);
- }
-
- @Override
- public final void onStringConfigChanged(int item, String value) throws RemoteException {
- onConfigChanged(item, value);
- }
-
- /**
- * Called when the IMS configuration has changed.
- * @param item the IMS configuration key constant, as defined in ImsConfig.
- * @param value the new integer value of the IMS configuration constant.
- */
- public void onConfigChanged(int item, int value) {
- // Base Implementation
- }
-
- /**
- * Called when the IMS configuration has changed.
- * @param item the IMS configuration key constant, as defined in ImsConfig.
- * @param value the new String value of the IMS configuration constant.
- */
- public void onConfigChanged(int item, String value) {
- // Base Implementation
- }
- }
-
- /**
* The configuration requested resulted in an unknown result. This may happen if the
* IMS configurations are unavailable.
*/
@@ -263,6 +230,16 @@ public class ImsConfigImplBase {
*/
public static final int CONFIG_RESULT_FAILED = 1;
+ /**
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "CONFIG_RESULT_", value = {
+ CONFIG_RESULT_SUCCESS,
+ CONFIG_RESULT_FAILED
+ })
+ public @interface SetConfigResult {}
+
private final RemoteCallbackList<IImsConfigCallback> mCallbacks = new RemoteCallbackList<>();
ImsConfigStub mImsConfigStub;
@@ -279,17 +256,16 @@ public class ImsConfigImplBase {
}
/**
- * Adds a {@link Callback} to the list of callbacks notified when a value in the configuration
- * changes.
+ * Adds a {@link android.telephony.ims.ProvisioningManager.Callback} to the list of callbacks
+ * notified when a value in the configuration changes.
* @param c callback to add.
*/
private void addImsConfigCallback(IImsConfigCallback c) {
mCallbacks.register(c);
}
/**
- * Removes a {@link Callback} to the list of callbacks notified when a value in the
- * configuration changes.
- *
+ * Removes a {@link android.telephony.ims.ProvisioningManager.Callback} to the list of callbacks
+ * notified when a value in the configuration changes.
* @param c callback to remove.
*/
private void removeImsConfigCallback(IImsConfigCallback c) {
@@ -370,10 +346,9 @@ public class ImsConfigImplBase {
*
* @param item an integer key.
* @param value an integer containing the configuration value.
- * @return the result of setting the configuration value, defined as either
- * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
+ * @return the result of setting the configuration value.
*/
- public int setConfig(int item, int value) {
+ public @SetConfigResult int setConfig(int item, int value) {
// Base Implementation - To be overridden.
return CONFIG_RESULT_FAILED;
}
@@ -383,10 +358,9 @@ public class ImsConfigImplBase {
*
* @param item an integer key.
* @param value a String containing the new configuration value.
- * @return Result of setting the configuration value, defined as either
- * {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
+ * @return Result of setting the configuration value.
*/
- public int setConfig(int item, String value) {
+ public @SetConfigResult int setConfig(int item, String value) {
// Base Implementation - To be overridden.
return CONFIG_RESULT_FAILED;
}
diff --git a/telephony/java/com/android/ims/ImsConfig.java b/telephony/java/com/android/ims/ImsConfig.java
index 90e9880bd03e..71a21743a449 100644
--- a/telephony/java/com/android/ims/ImsConfig.java
+++ b/telephony/java/com/android/ims/ImsConfig.java
@@ -16,12 +16,17 @@
package com.android.ims;
-import android.content.Context;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.Looper;
import android.os.RemoteException;
import android.telephony.Rlog;
import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ProvisioningManager;
import android.telephony.ims.aidl.IImsConfig;
-import android.telephony.ims.stub.ImsConfigImplBase;
+import android.telephony.ims.aidl.IImsConfigCallback;
+
+import java.util.concurrent.Executor;
/**
* Provides APIs to get/set the IMS service feature/capability/parameters.
@@ -29,8 +34,10 @@ import android.telephony.ims.stub.ImsConfigImplBase;
* 1) Items provisioned by the operator.
* 2) Items configured by user. Mainly service feature class.
*
+ * @deprecated Use {@link ProvisioningManager} to change these configurations in the ImsService.
* @hide
*/
+@Deprecated
public class ImsConfig {
private static final String TAG = "ImsConfig";
private boolean DBG = true;
@@ -46,7 +53,7 @@ public class ImsConfig {
/**
* Broadcast action: the configuration was changed
- * @deprecated Use {@link ImsConfig#addConfigCallback(ImsConfigImplBase.Callback)} instead.
+ * @deprecated Use {@link android.telephony.ims.ProvisioningManager.Callback} instead.
* @hide
*/
public static final String ACTION_IMS_CONFIG_CHANGED =
@@ -673,13 +680,25 @@ public class ImsConfig {
}
/**
- * Adds a {@link ImsConfigImplBase.Callback} to the ImsService to notify when a Configuration
+ * Adds a {@link ProvisioningManager.Callback} to the ImsService to notify when a Configuration
* item has changed.
*
- * Make sure to call {@link #removeConfigCallback(ImsConfigImplBase.Callback)} when finished
+ * Make sure to call {@link #removeConfigCallback(IImsConfigCallback)} when finished
* using this callback.
*/
- public void addConfigCallback(ImsConfigImplBase.Callback callback) throws ImsException {
+ public void addConfigCallback(ProvisioningManager.Callback callback) throws ImsException {
+ callback.setExecutor(getThreadExecutor());
+ addConfigCallback(callback.getBinder());
+ }
+
+ /**
+ * Adds a {@link IImsConfigCallback} to the ImsService to notify when a Configuration
+ * item has changed.
+ *
+ * Make sure to call {@link #removeConfigCallback(IImsConfigCallback)} when finished
+ * using this callback.
+ */
+ public void addConfigCallback(IImsConfigCallback callback) throws ImsException {
if (DBG) Rlog.d(TAG, "addConfigCallback: " + callback);
try {
miConfig.addImsConfigCallback(callback);
@@ -690,10 +709,9 @@ public class ImsConfig {
}
/**
- * Removes a {@link ImsConfigImplBase.Callback} from the ImsService that was previously added
- * by {@link #addConfigCallback(ImsConfigImplBase.Callback)}.
+ * Removes an existing {@link IImsConfigCallback} from the ImsService.
*/
- public void removeConfigCallback(ImsConfigImplBase.Callback callback) throws ImsException {
+ public void removeConfigCallback(IImsConfigCallback callback) throws ImsException {
if (DBG) Rlog.d(TAG, "removeConfigCallback: " + callback);
try {
miConfig.removeImsConfigCallback(callback);
@@ -709,4 +727,11 @@ public class ImsConfig {
public boolean isBinderAlive() {
return miConfig.asBinder().isBinderAlive();
}
+
+ private Executor getThreadExecutor() {
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+ return new HandlerExecutor(new Handler(Looper.myLooper()));
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 4bdec088b6a1..bc4451977d92 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -165,13 +165,23 @@ interface ISub {
int setOpportunistic(boolean opportunistic, int subId);
/**
- * Set parent subId by simInfo index
+ * Inform SubscriptionManager that subscriptions in the list are bundled
+ * as a group. Typically it's a primary subscription and an opportunistic
+ * subscription. It should only affect multi-SIM scenarios where primary
+ * and opportunistic subscriptions can be activated together.
+ * Being in the same group means they might be activated or deactivated
+ * together, some of them may be invisible to the users, etc.
+ *
+ * Caller will either have {@link android.Manifest.permission.MODIFY_PHONE_STATE}
+ * permission or can manage all subscriptions in the list, according to their
+ * acess rules.
+ *
+ * @param subIdList list of subId that will be in the same group
+ * @return groupUUID a UUID assigned to the subscription group. It returns
+ * null if fails.
*
- * @param parentSubId: subId of its parent subscription.
- * @param subId the unique SubscriptionInfo index in database
- * @return the number of records updated
*/
- int setParentSubId(int parentSubId, int subId);
+ String setSubscriptionGroup(in int[] subIdList, String callingPackage);
/**
* Set which subscription is preferred for cellular data. It's
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 3aaa32344e0b..85a9cf57ed4b 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -40,6 +40,7 @@ import android.telephony.TelephonyHistogram;
import android.telephony.VisualVoicemailSmsFilterSettings;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsConfigCallback;
import android.telephony.ims.aidl.IImsMmTelFeature;
import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
@@ -1569,24 +1570,24 @@ interface ITelephony {
/**
* Adds an IMS registration status callback for the subscription id specified.
*/
- oneway void addImsRegistrationCallback(int subId, IImsRegistrationCallback c,
+ void addImsRegistrationCallback(int subId, IImsRegistrationCallback c,
String callingPackage);
/**
* Removes an existing IMS registration status callback for the subscription specified.
*/
- oneway void removeImsRegistrationCallback(int subId, IImsRegistrationCallback c,
+ void removeImsRegistrationCallback(int subId, IImsRegistrationCallback c,
String callingPackage);
/**
* Adds an IMS MmTel capabilities callback for the subscription specified.
*/
- oneway void addMmTelCapabilityCallback(int subId, IImsCapabilityCallback c,
+ void addMmTelCapabilityCallback(int subId, IImsCapabilityCallback c,
String callingPackage);
/**
* Removes an existing IMS MmTel capabilities callback for the subscription specified.
*/
- oneway void removeMmTelCapabilityCallback(int subId, IImsCapabilityCallback c,
+ void removeMmTelCapabilityCallback(int subId, IImsCapabilityCallback c,
String callingPackage);
/**
@@ -1691,4 +1692,34 @@ interface ITelephony {
* Return a list of certs in hex string from loaded carrier privileges access rules.
*/
List<String> getCertsFromCarrierPrivilegeAccessRules(int subId);
+
+ /**
+ * Register an IMS provisioning change callback with Telephony.
+ */
+ void registerImsProvisioningChangedCallback(int subId, IImsConfigCallback callback);
+
+ /**
+ * unregister an existing IMS provisioning change callback.
+ */
+ void unregisterImsProvisioningChangedCallback(int subId, IImsConfigCallback callback);
+
+ /**
+ * Return an integer containing the provisioning value for the specified provisioning key.
+ */
+ int getImsProvisioningInt(int subId, int key);
+
+ /**
+ * return a String containing the provisioning value for the provisioning key specified.
+ */
+ String getImsProvisioningString(int subId, int key);
+
+ /**
+ * Set the integer provisioning value for the provisioning key specified.
+ */
+ int setImsProvisioningInt(int subId, int key, int value);
+
+ /**
+ * Set the String provisioning value for the provisioning key specified.
+ */
+ int setImsProvisioningString(int subId, int key, String value);
}
diff --git a/test-mock/api/current.txt b/test-mock/api/current.txt
index fc9b4c6831e8..f91d74a30693 100644
--- a/test-mock/api/current.txt
+++ b/test-mock/api/current.txt
@@ -31,6 +31,7 @@ package android.test.mock {
public class MockContext extends android.content.Context {
ctor public MockContext();
+ method public boolean bindIsolatedService(android.content.Intent, android.content.ServiceConnection, int, java.lang.String);
method public boolean bindService(android.content.Intent, android.content.ServiceConnection, int);
method public int checkCallingOrSelfPermission(java.lang.String);
method public int checkCallingOrSelfUriPermission(android.net.Uri, int);
diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
index fa5b896ea126..66be6d9d9840 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -576,6 +576,13 @@ public class MockContext extends Context {
throw new UnsupportedOperationException();
}
+ @Override
+ public boolean bindIsolatedService(Intent service,
+ ServiceConnection conn, int flags,
+ String instanceName) {
+ throw new UnsupportedOperationException();
+ }
+
/** @hide */
@Override
public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
diff --git a/test-runner/src/android/test/IsolatedContext.java b/test-runner/src/android/test/IsolatedContext.java
index 6e4c41eef81c..73db4517e130 100644
--- a/test-runner/src/android/test/IsolatedContext.java
+++ b/test-runner/src/android/test/IsolatedContext.java
@@ -75,6 +75,12 @@ public class IsolatedContext extends ContextWrapper {
}
@Override
+ public boolean bindIsolatedService(Intent service, ServiceConnection conn, int flags,
+ String instanceName) {
+ return false;
+ }
+
+ @Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return null;
}
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index 0bc5221245ca..583f14ac0cbd 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -431,7 +431,7 @@ void Debug::DumpHex(const void* data, size_t len) {
void Debug::DumpResStringPool(const android::ResStringPool* pool, text::Printer* printer) {
using namespace android;
-
+
if (pool->getError() == NO_INIT) {
printer->Print("String pool is unitialized.\n");
return;
@@ -460,7 +460,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/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index dbe5ac5adb98..da22e885b917 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -718,7 +718,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)));
+ str, StringPool::Context(StringPool::Context::kHighPriority, config), data));
if (type == ResourceType::kRaw) {
file_ref->type = ResourceFile::Type::kUnknown;
} else if (util::EndsWith(*file_ref->path, ".xml")) {
@@ -730,7 +730,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)));
+ return util::make_unique<String>(dst_pool->MakeRef(str, StringPool::Context(config), data));
}
} break;
diff --git a/tools/aapt2/StringPool.cpp b/tools/aapt2/StringPool.cpp
index 8eabd3225d87..a8c26668b3a5 100644
--- a/tools/aapt2/StringPool.cpp
+++ b/tools/aapt2/StringPool.cpp
@@ -165,12 +165,13 @@ StringPool::Ref StringPool::MakeRef(const StringPiece& str) {
return MakeRefImpl(str, Context{}, true);
}
-StringPool::Ref StringPool::MakeRef(const StringPiece& str, const Context& context) {
- 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::MakeRefImpl(const StringPiece& str, const Context& context,
- bool unique) {
+ bool unique, Maybe<size_t> index) {
if (unique) {
auto range = indexed_strings_.equal_range(str);
for (auto iter = range.first; iter != range.second; ++iter) {
@@ -180,15 +181,26 @@ 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_ = strings_.size();
+ entry->index_ = insertion_index;
entry->ref_ = 0;
entry->pool_ = this;
Entry* borrow = entry.get();
- strings_.emplace_back(std::move(entry));
+ 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);
+ }
+
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 1006ca970dc5..115d5d315b8f 100644
--- a/tools/aapt2/StringPool.h
+++ b/tools/aapt2/StringPool.h
@@ -166,7 +166,8 @@ 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);
+ Ref MakeRef(const android::StringPiece& str, const Context& context,
+ Maybe<size_t> index = {});
// Adds a string from another string pool. Returns a reference to the string in the string pool.
Ref MakeRef(const Ref& ref);
@@ -210,7 +211,8 @@ 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);
+ Ref MakeRefImpl(const android::StringPiece& str, const Context& context, bool unique,
+ Maybe<size_t> index = {});
void ReAssignIndices();
std::vector<std::unique_ptr<Entry>> strings_;
diff --git a/tools/aapt2/StringPool_test.cpp b/tools/aapt2/StringPool_test.cpp
index 9a7238b584ba..648be7d33754 100644
--- a/tools/aapt2/StringPool_test.cpp
+++ b/tools/aapt2/StringPool_test.cpp
@@ -84,6 +84,24 @@ 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 3ea17552ea7c..4492f6b49cf0 100644
--- a/tools/aapt2/cmd/Convert.cpp
+++ b/tools/aapt2/cmd/Convert.cpp
@@ -57,78 +57,6 @@ class IApkSerializer {
Source source_;
};
-bool ConvertApk(IAaptContext* context, unique_ptr<LoadedApk> apk, IApkSerializer* serializer,
- IArchiveWriter* writer) {
- io::IFile* manifest = apk->GetFileCollection()->FindFile(kAndroidManifestPath);
- if (!serializer->SerializeXml(apk->GetManifest(), kAndroidManifestPath, true /*utf16*/, writer,
- (manifest != nullptr && manifest->WasCompressed())
- ? ArchiveEntry::kCompress : 0u)) {
- context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
- << "failed to serialize AndroidManifest.xml");
- return false;
- }
-
- if (apk->GetResourceTable() != nullptr) {
- // The table might be modified by below code.
- auto converted_table = apk->GetResourceTable();
-
- // Resources
- for (const auto& package : converted_table->packages) {
- for (const auto& type : package->types) {
- for (const auto& entry : type->entries) {
- for (const auto& config_value : entry->values) {
- FileReference* file = ValueCast<FileReference>(config_value->value.get());
- if (file != nullptr) {
- if (file->file == nullptr) {
- context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
- << "no file associated with " << *file);
- return false;
- }
-
- if (!serializer->SerializeFile(file, writer)) {
- context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
- << "failed to serialize file " << *file->path);
- return false;
- }
- } // file
- } // config_value
- } // entry
- } // type
- } // package
-
- // Converted resource table
- if (!serializer->SerializeTable(converted_table, writer)) {
- context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
- << "failed to serialize the resource table");
- return false;
- }
- }
-
- // Other files
- std::unique_ptr<io::IFileCollectionIterator> iterator = apk->GetFileCollection()->Iterator();
- while (iterator->HasNext()) {
- io::IFile* file = iterator->Next();
- std::string path = file->GetSource().path;
-
- // Manifest, resource table and resources have already been taken care of.
- if (path == kAndroidManifestPath ||
- path == kApkResourceTablePath ||
- path == kProtoResourceTablePath ||
- path.find("res/") == 0) {
- continue;
- }
-
- if (!io::CopyFileToArchivePreserveCompression(context, file, path, writer)) {
- context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
- << "failed to copy file " << path);
- return false;
- }
- }
-
- return true;
-}
-
-
class BinaryApkSerializer : public IApkSerializer {
public:
BinaryApkSerializer(IAaptContext* context, const Source& source,
@@ -323,12 +251,97 @@ class Context : public IAaptContext {
StdErrDiagnostics diag_;
};
+int Convert(IAaptContext* context, LoadedApk* apk, IArchiveWriter* output_writer,
+ ApkFormat output_format, TableFlattenerOptions& options) {
+ // Do not change the ordering of strings in the values string pool
+ options.sort_stringpool_entries = false;
+
+ unique_ptr<IApkSerializer> serializer;
+ if (output_format == ApkFormat::kBinary) {
+ serializer.reset(new BinaryApkSerializer(context, apk->GetSource(), options));
+ } else if (output_format == ApkFormat::kProto) {
+ serializer.reset(new ProtoApkSerializer(context, apk->GetSource()));
+ } else {
+ context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+ << "Cannot convert APK to unknown format");
+ return 1;
+ }
+
+ io::IFile* manifest = apk->GetFileCollection()->FindFile(kAndroidManifestPath);
+ if (!serializer->SerializeXml(apk->GetManifest(), kAndroidManifestPath, true /*utf16*/,
+ output_writer, (manifest != nullptr && manifest->WasCompressed())
+ ? ArchiveEntry::kCompress : 0u)) {
+ context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+ << "failed to serialize AndroidManifest.xml");
+ return 1;
+ }
+
+ if (apk->GetResourceTable() != nullptr) {
+ // The table might be modified by below code.
+ auto converted_table = apk->GetResourceTable();
+
+ // Resources
+ for (const auto& package : converted_table->packages) {
+ for (const auto& type : package->types) {
+ for (const auto& entry : type->entries) {
+ for (const auto& config_value : entry->values) {
+ FileReference* file = ValueCast<FileReference>(config_value->value.get());
+ if (file != nullptr) {
+ if (file->file == nullptr) {
+ context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+ << "no file associated with " << *file);
+ return 1;
+ }
+
+ if (!serializer->SerializeFile(file, output_writer)) {
+ context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+ << "failed to serialize file " << *file->path);
+ return 1;
+ }
+ } // file
+ } // config_value
+ } // entry
+ } // type
+ } // package
+
+ // Converted resource table
+ if (!serializer->SerializeTable(converted_table, output_writer)) {
+ context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+ << "failed to serialize the resource table");
+ return 1;
+ }
+ }
+
+ // Other files
+ std::unique_ptr<io::IFileCollectionIterator> iterator = apk->GetFileCollection()->Iterator();
+ while (iterator->HasNext()) {
+ io::IFile* file = iterator->Next();
+ std::string path = file->GetSource().path;
+
+ // Manifest, resource table and resources have already been taken care of.
+ if (path == kAndroidManifestPath ||
+ path == kApkResourceTablePath ||
+ path == kProtoResourceTablePath ||
+ path.find("res/") == 0) {
+ continue;
+ }
+
+ if (!io::CopyFileToArchivePreserveCompression(context, file, path, output_writer)) {
+ context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
+ << "failed to copy file " << path);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
const char* ConvertCommand::kOutputFormatProto = "proto";
const char* ConvertCommand::kOutputFormatBinary = "binary";
int ConvertCommand::Action(const std::vector<std::string>& args) {
if (args.size() != 1) {
- std::cerr << "must supply a single proto APK\n";
+ std::cerr << "must supply a single APK\n";
Usage(&std::cerr);
return 1;
}
@@ -341,34 +354,31 @@ int ConvertCommand::Action(const std::vector<std::string>& args) {
return 1;
}
- Maybe<AppInfo> app_info =
- ExtractAppInfoFromBinaryManifest(*apk->GetManifest(), context.GetDiagnostics());
+ Maybe<AppInfo> app_info = ExtractAppInfoFromBinaryManifest(*apk->GetManifest(),
+ context.GetDiagnostics());
if (!app_info) {
return 1;
}
context.package_ = app_info.value().package;
-
- unique_ptr<IArchiveWriter> writer =
- CreateZipFileArchiveWriter(context.GetDiagnostics(), output_path_);
+ unique_ptr<IArchiveWriter> writer = CreateZipFileArchiveWriter(context.GetDiagnostics(),
+ output_path_);
if (writer == nullptr) {
return 1;
}
- unique_ptr<IApkSerializer> serializer;
+ ApkFormat format;
if (!output_format_ || output_format_.value() == ConvertCommand::kOutputFormatBinary) {
-
- serializer.reset(new BinaryApkSerializer(&context, apk->GetSource(), options_));
+ format = ApkFormat::kBinary;
} else if (output_format_.value() == ConvertCommand::kOutputFormatProto) {
- serializer.reset(new ProtoApkSerializer(&context, apk->GetSource()));
+ format = ApkFormat::kProto;
} else {
- context.GetDiagnostics()->Error(DiagMessage(path)
- << "Invalid value for flag --output-format: "
- << output_format_.value());
+ context.GetDiagnostics()->Error(DiagMessage(path) << "Invalid value for flag --output-format: "
+ << output_format_.value());
return 1;
}
- return ConvertApk(&context, std::move(apk), serializer.get(), writer.get()) ? 0 : 1;
+ return Convert(&context, apk.get(), writer.get(), format, options_);
}
} // namespace aapt
diff --git a/tools/aapt2/cmd/Convert.h b/tools/aapt2/cmd/Convert.h
index fcec23d16f78..6a6719c91b58 100644
--- a/tools/aapt2/cmd/Convert.h
+++ b/tools/aapt2/cmd/Convert.h
@@ -18,6 +18,7 @@
#define AAPT2_CONVERT_H
#include "Command.h"
+#include "LoadedApk.h"
#include "format/binary/TableFlattener.h"
namespace aapt {
@@ -49,6 +50,9 @@ class ConvertCommand : public Command {
bool verbose_ = false;
};
-}// namespace aapt
+int Convert(IAaptContext* context, LoadedApk* input, IArchiveWriter* output_writer,
+ ApkFormat output_format, TableFlattenerOptions& options);
+
+} // namespace aapt
#endif //AAPT2_CONVERT_H
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index 8a86f63a30c1..6c1a9ba2cbad 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -573,15 +573,17 @@ class PackageFlattener {
} // namespace
bool TableFlattener::Consume(IAaptContext* context, ResourceTable* table) {
- // 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;
- });
+ 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;
+ });
+ }
// 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 c2e1d4b4ce8c..635cb21f514c 100644
--- a/tools/aapt2/format/binary/TableFlattener.h
+++ b/tools/aapt2/format/binary/TableFlattener.h
@@ -43,6 +43,9 @@ 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;
};
class TableFlattener : public IResourceTableConsumer {
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 1fd68ec1df70..7ca3c53154aa 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -61,9 +61,7 @@ interface IWifiManager
ParceledListSlice getPrivilegedConfiguredNetworks();
- WifiConfiguration getMatchingWifiConfig(in ScanResult scanResult);
-
- List<WifiConfiguration> getAllMatchingWifiConfigs(in ScanResult scanResult);
+ List<WifiConfiguration> getAllMatchingWifiConfigs(in List<ScanResult> scanResult);
List<OsuProvider> getMatchingOsuProviders(in ScanResult scanResult);
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 8fc9b9759469..b34ac264ade4 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -58,7 +58,7 @@ public class WifiConfiguration implements Parcelable {
/**
* Current Version of the Backup Serializer.
*/
- private static final int BACKUP_VERSION = 2;
+ private static final int BACKUP_VERSION = 3;
/** {@hide} */
public static final String ssidVarName = "ssid";
/** {@hide} */
@@ -2420,6 +2420,7 @@ public class WifiConfiguration implements Parcelable {
out.writeInt(apChannel);
BackupUtils.writeString(out, preSharedKey);
out.writeInt(getAuthType());
+ out.writeBoolean(hiddenSSID);
return baos.toByteArray();
}
@@ -2442,6 +2443,9 @@ public class WifiConfiguration implements Parcelable {
config.apChannel = in.readInt();
config.preSharedKey = BackupUtils.readString(in);
config.allowedKeyManagement.set(in.readInt());
+ if (version >= 3) {
+ config.hiddenSSID = in.readBoolean();
+ }
return config;
}
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 954b51f02820..4b6f5fac408a 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1073,42 +1073,27 @@ public class WifiManager {
}
/**
- * Returns a WifiConfiguration matching this ScanResult
- *
- * @param scanResult scanResult that represents the BSSID
- * @return {@link WifiConfiguration} that matches this BSSID or null
- * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
- * @hide
- */
- @UnsupportedAppUsage
- public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) {
- try {
- return mService.getMatchingWifiConfig(scanResult);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Return all matching WifiConfigurations for this ScanResult.
+ * Returns all matching WifiConfigurations for a given list of ScanResult.
*
* An empty list will be returned when no configurations are installed or if no configurations
* match the ScanResult.
- *
- * @param scanResult scanResult that represents the BSSID
- * @return A list of {@link WifiConfiguration}
+
+ * @param scanResults a list of scanResult that represents the BSSID
+ * @return A list of {@link WifiConfiguration} that can have duplicate entries.
* @throws UnsupportedOperationException if Passpoint is not enabled on the device.
* @hide
*/
- public List<WifiConfiguration> getAllMatchingWifiConfigs(ScanResult scanResult) {
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+ public List<WifiConfiguration> getAllMatchingWifiConfigs(
+ @NonNull List<ScanResult> scanResults) {
try {
- return mService.getAllMatchingWifiConfigs(scanResult);
+ return mService.getAllMatchingWifiConfigs(scanResults);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
-
/**
* Returns a list of Hotspot 2.0 OSU (Online Sign-Up) providers associated with the given AP.
*
@@ -1119,6 +1104,7 @@ public class WifiManager {
* @throws UnsupportedOperationException if Passpoint is not enabled on the device.
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
public List<OsuProvider> getMatchingOsuProviders(ScanResult scanResult) {
try {
return mService.getMatchingOsuProviders(scanResult);
@@ -4256,27 +4242,21 @@ public class WifiManager {
/**
* @return true if this device supports WPA3-Personal SAE
- * @hide
*/
- @SystemApi
public boolean isWpa3SaeSupported() {
return isFeatureSupported(WIFI_FEATURE_WPA3_SAE);
}
/**
* @return true if this device supports WPA3-Enterprise Suite-B-192
- * @hide
*/
- @SystemApi
public boolean isWpa3SuiteBSupported() {
return isFeatureSupported(WIFI_FEATURE_WPA3_SUITE_B);
}
/**
* @return true if this device supports Wi-Fi Enhanced Open (OWE)
- * @hide
*/
- @SystemApi
public boolean isOweSupported() {
return isFeatureSupported(WIFI_FEATURE_OWE);
}
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 71d4173a389c..26bdb181e4a1 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -20,10 +20,10 @@ import android.net.wifi.hotspot2.pps.Credential;
import android.net.wifi.hotspot2.pps.HomeSp;
import android.net.wifi.hotspot2.pps.Policy;
import android.net.wifi.hotspot2.pps.UpdateParameter;
+import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
-import android.os.Parcel;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
@@ -467,24 +467,54 @@ public final class PasspointConfiguration implements Parcelable {
}
/**
- * Validate the configuration data.
+ * Validate the R1 configuration data.
*
* @return true on success or false on failure
* @hide
*/
public boolean validate() {
- if (mHomeSp == null || !mHomeSp.validate()) {
+ // Optional: PerProviderSubscription/<X+>/SubscriptionUpdate
+ if (mSubscriptionUpdate != null && !mSubscriptionUpdate.validate()) {
return false;
}
- if (mCredential == null || !mCredential.validate()) {
+ return validateForCommonR1andR2(true);
+ }
+
+ /**
+ * Validate the R2 configuration data.
+ *
+ * @return true on success or false on failure
+ * @hide
+ */
+ public boolean validateForR2() {
+ // Required: PerProviderSubscription/UpdateIdentifier
+ if (mUpdateIdentifier == Integer.MIN_VALUE) {
return false;
}
- if (mPolicy != null && !mPolicy.validate()) {
+
+ // Required: PerProviderSubscription/<X+>/SubscriptionUpdate
+ if (mSubscriptionUpdate == null || !mSubscriptionUpdate.validate()) {
return false;
}
- if (mSubscriptionUpdate != null && !mSubscriptionUpdate.validate()) {
+ return validateForCommonR1andR2(false);
+ }
+
+ private boolean validateForCommonR1andR2(boolean isR1) {
+ // Required: PerProviderSubscription/<X+>/HomeSP
+ if (mHomeSp == null || !mHomeSp.validate()) {
+ return false;
+ }
+
+ // Required: PerProviderSubscription/<X+>/Credential
+ if (mCredential == null || !mCredential.validate(isR1)) {
+ return false;
+ }
+
+ // Optional: PerProviderSubscription/<X+>/Policy
+ if (mPolicy != null && !mPolicy.validate()) {
return false;
}
+
if (mTrustRootCertList != null) {
for (Map.Entry<String, byte[]> entry : mTrustRootCertList.entrySet()) {
String url = entry.getKey();
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index e8fcbfd6731e..7689fc34ff5b 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -18,8 +18,8 @@ package android.net.wifi.hotspot2.pps;
import android.net.wifi.EAPConstants;
import android.net.wifi.ParcelUtil;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
@@ -1019,10 +1019,11 @@ public final class Credential implements Parcelable {
/**
* Validate the configuration data.
*
+ * @param isR1 {@code true} if the configuration is for R1
* @return true on success or false on failure
* @hide
*/
- public boolean validate() {
+ public boolean validate(boolean isR1) {
if (TextUtils.isEmpty(mRealm)) {
Log.d(TAG, "Missing realm");
return false;
@@ -1035,11 +1036,11 @@ public final class Credential implements Parcelable {
// Verify the credential.
if (mUserCredential != null) {
- if (!verifyUserCredential()) {
+ if (!verifyUserCredential(isR1)) {
return false;
}
} else if (mCertCredential != null) {
- if (!verifyCertCredential()) {
+ if (!verifyCertCredential(isR1)) {
return false;
}
} else if (mSimCredential != null) {
@@ -1081,9 +1082,10 @@ public final class Credential implements Parcelable {
/**
* Verify user credential.
*
+ * @param isR1 {@code true} if credential is for R1
* @return true if user credential is valid, false otherwise.
*/
- private boolean verifyUserCredential() {
+ private boolean verifyUserCredential(boolean isR1) {
if (mUserCredential == null) {
Log.d(TAG, "Missing user credential");
return false;
@@ -1095,7 +1097,10 @@ public final class Credential implements Parcelable {
if (!mUserCredential.validate()) {
return false;
}
- if (mCaCertificate == null) {
+
+ // CA certificate is required for R1 Passpoint profile.
+ // For R2, it is downloaded using cert URL provided in PPS MO after validation completes.
+ if (isR1 && mCaCertificate == null) {
Log.d(TAG, "Missing CA Certificate for user credential");
return false;
}
@@ -1106,9 +1111,10 @@ public final class Credential implements Parcelable {
* Verify certificate credential, which is used for EAP-TLS. This will verify
* that the necessary client key and certificates are provided.
*
+ * @param isR1 {@code true} if credential is for R1
* @return true if certificate credential is valid, false otherwise.
*/
- private boolean verifyCertCredential() {
+ private boolean verifyCertCredential(boolean isR1) {
if (mCertCredential == null) {
Log.d(TAG, "Missing certificate credential");
return false;
@@ -1123,7 +1129,9 @@ public final class Credential implements Parcelable {
}
// Verify required key and certificates for certificate credential.
- if (mCaCertificate == null) {
+ // CA certificate is required for R1 Passpoint profile.
+ // For R2, it is downloaded using cert URL provided in PPS MO after validation completes.
+ if (isR1 && mCaCertificate == null) {
Log.d(TAG, "Missing CA Certificate for certificate credential");
return false;
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index e6892bea4595..f58a006278d2 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -491,6 +491,17 @@ public class WifiP2pManager {
/** @hide */
public static final int FACTORY_RESET_SUCCEEDED = BASE + 84;
+ /** @hide */
+ public static final int REQUEST_ONGOING_PEER_CONFIG = BASE + 85;
+ /** @hide */
+ public static final int RESPONSE_ONGOING_PEER_CONFIG = BASE + 86;
+ /** @hide */
+ public static final int SET_ONGOING_PEER_CONFIG = BASE + 87;
+ /** @hide */
+ public static final int SET_ONGOING_PEER_CONFIG_FAILED = BASE + 88;
+ /** @hide */
+ public static final int SET_ONGOING_PEER_CONFIG_SUCCEEDED = BASE + 89;
+
/**
* Create a new WifiP2pManager instance. Applications use
* {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
@@ -680,6 +691,18 @@ public class WifiP2pManager {
}
/**
+ * Interface for callback invocation when ongoing peer info is available
+ * @hide
+ */
+ public interface OngoingPeerInfoListener {
+ /**
+ * The requested ongoing WifiP2pConfig is available
+ * @param peerConfig WifiP2pConfig for current connecting session
+ */
+ void onOngoingPeerAvailable(WifiP2pConfig peerConfig);
+ }
+
+ /**
* A channel that connects the application to the Wifi p2p framework.
* Most p2p operations require a Channel as an argument. An instance of Channel is obtained
* by doing a call on {@link #initialize}
@@ -787,6 +810,7 @@ public class WifiP2pManager {
case SET_CHANNEL_FAILED:
case REPORT_NFC_HANDOVER_FAILED:
case FACTORY_RESET_FAILED:
+ case SET_ONGOING_PEER_CONFIG_FAILED:
if (listener != null) {
((ActionListener) listener).onFailure(message.arg1);
}
@@ -814,6 +838,7 @@ public class WifiP2pManager {
case SET_CHANNEL_SUCCEEDED:
case REPORT_NFC_HANDOVER_SUCCEEDED:
case FACTORY_RESET_SUCCEEDED:
+ case SET_ONGOING_PEER_CONFIG_SUCCEEDED:
if (listener != null) {
((ActionListener) listener).onSuccess();
}
@@ -857,6 +882,13 @@ public class WifiP2pManager {
.onHandoverMessageAvailable(handoverMessage);
}
break;
+ case RESPONSE_ONGOING_PEER_CONFIG:
+ WifiP2pConfig peerConfig = (WifiP2pConfig) message.obj;
+ if (listener != null) {
+ ((OngoingPeerInfoListener) listener)
+ .onOngoingPeerAvailable(peerConfig);
+ }
+ break;
default:
Log.d(TAG, "Ignored " + message);
break;
@@ -1536,6 +1568,7 @@ public class WifiP2pManager {
/**
* Removes all saved p2p groups.
+ *
* @param c is the channel created at {@link #initialize}.
* @param listener for callback on success or failure. Can be null.
* @hide
@@ -1550,4 +1583,37 @@ public class WifiP2pManager {
callingPackage);
}
+ /**
+ * Request saved WifiP2pConfig which used for an ongoing peer connection
+ *
+ * @param c is the channel created at {@link #initialize}
+ * @param listener for callback when ongoing peer config updated. Can't be null.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
+ public void requestOngoingPeerConfig(@NonNull Channel c,
+ @NonNull OngoingPeerInfoListener listener) {
+ checkChannel(c);
+ c.mAsyncChannel.sendMessage(REQUEST_ONGOING_PEER_CONFIG,
+ Binder.getCallingUid(), c.putListener(listener));
+ }
+
+ /**
+ * Set saved WifiP2pConfig which used for an ongoing peer connection
+ *
+ * @param c is the channel created at {@link #initialize}
+ * @param config used for change an ongoing peer connection
+ * @param listener for callback when ongoing peer config updated. Can be null.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
+ public void setOngoingPeerConfig(@NonNull Channel c, @NonNull WifiP2pConfig config,
+ @Nullable ActionListener listener) {
+ checkChannel(c);
+ checkP2pConfig(config);
+ c.mAsyncChannel.sendMessage(SET_ONGOING_PEER_CONFIG, 0,
+ c.putListener(listener), config);
+ }
}
diff --git a/wifi/java/com/android/server/wifi/AbstractWifiService.java b/wifi/java/com/android/server/wifi/AbstractWifiService.java
index eede23b22387..6cdef5051524 100644
--- a/wifi/java/com/android/server/wifi/AbstractWifiService.java
+++ b/wifi/java/com/android/server/wifi/AbstractWifiService.java
@@ -25,7 +25,6 @@ import android.net.wifi.INetworkRequestMatchCallback;
import android.net.wifi.ISoftApCallback;
import android.net.wifi.ITrafficStateCallback;
import android.net.wifi.IWifiManager;
-import android.net.wifi.PasspointManagementObjectDefinition;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiActivityEnergyInfo;
import android.net.wifi.WifiConfiguration;
@@ -37,7 +36,6 @@ import android.os.IBinder;
import android.os.Messenger;
import android.os.ResultReceiver;
import android.os.WorkSource;
-import android.util.Slog;
import java.util.List;
@@ -83,17 +81,34 @@ public abstract class AbstractWifiService extends IWifiManager.Stub {
throw new UnsupportedOperationException();
}
- @Override
+ /**
+ * Returns a WifiConfiguration matching this ScanResult
+ * @param scanResult a single ScanResult Object
+ * @return
+ * @deprecated use {@link #getAllMatchingWifiConfigs(List)} instead.
+ */
+ @Deprecated
public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) {
throw new UnsupportedOperationException();
}
- @Override
+ /**
+ * Returns all matching WifiConfigurations for this ScanResult.
+ * @param scanResult a single ScanResult Object
+ * @return
+ * @deprecated use {@link #getAllMatchingWifiConfigs(List)} instead.
+ */
+ @Deprecated
public List<WifiConfiguration> getAllMatchingWifiConfigs(ScanResult scanResult) {
throw new UnsupportedOperationException();
}
@Override
+ public List<WifiConfiguration> getAllMatchingWifiConfigs(List<ScanResult> scanResults) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public List<OsuProvider> getMatchingOsuProviders(ScanResult scanResult) {
throw new UnsupportedOperationException();
}
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index 5f3e1b27672e..bf6feac1aba7 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import android.net.MacAddress;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
import android.os.Parcel;
import android.support.test.filters.SmallTest;
@@ -30,6 +31,9 @@ import android.support.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+
/**
* Unit tests for {@link android.net.wifi.WifiConfiguration}.
*/
@@ -242,4 +246,30 @@ public class WifiConfigurationTest {
config.setRandomizedMacAddress(null);
assertEquals(defaultMac, config.getRandomizedMacAddress());
}
+
+ /**
+ * Verifies that the serialization/de-serialization for softap config works.
+ */
+ @Test
+ public void testSoftApConfigBackupAndRestore() throws Exception {
+ WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "TestAP";
+ config.apBand = WifiConfiguration.AP_BAND_5GHZ;
+ config.apChannel = 40;
+ config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
+ config.preSharedKey = "TestPsk";
+ config.hiddenSSID = true;
+
+ byte[] data = config.getBytesForBackup();
+ ByteArrayInputStream bais = new ByteArrayInputStream(data);
+ DataInputStream in = new DataInputStream(bais);
+ WifiConfiguration restoredConfig = WifiConfiguration.getWifiConfigFromBackup(in);
+
+ assertEquals(config.SSID, restoredConfig.SSID);
+ assertEquals(config.preSharedKey, restoredConfig.preSharedKey);
+ assertEquals(config.getAuthType(), restoredConfig.getAuthType());
+ assertEquals(config.apBand, restoredConfig.apBand);
+ assertEquals(config.apChannel, restoredConfig.apChannel);
+ assertEquals(config.hiddenSSID, restoredConfig.hiddenSSID);
+ }
}
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index ea41bb39c4d5..ecf65c9d2905 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -35,7 +35,20 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyList;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -62,6 +75,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
+import java.util.List;
/**
* Unit tests for {@link android.net.wifi.WifiManager}.
@@ -1250,4 +1264,26 @@ i * Verify that a call to cancel WPS immediately returns a failure.
userSelectionCallbackCaptor.getValue().reject();
verify(iUserSelectionCallback).reject();
}
+
+ /**
+ * Check the call to getAllMatchingWifiConfigs calls getAllMatchingWifiConfigs of WifiService
+ * with the provided a list of ScanResult.
+ */
+ @Test
+ public void testGetAllMatchingWifiConfigs() throws Exception {
+ mWifiManager.getAllMatchingWifiConfigs(new ArrayList<>());
+
+ verify(mWifiService).getAllMatchingWifiConfigs(any(List.class));
+ }
+
+ /**
+ * Check the call to getMatchingOsuProviders calls getMatchingOsuProviders of WifiService
+ * with the provided a single ScanResult.
+ */
+ @Test
+ public void testGetMatchingOsuProviders() throws Exception {
+ mWifiManager.getMatchingOsuProviders(new ScanResult());
+
+ verify(mWifiService).getMatchingOsuProviders(any(ScanResult.class));
+ }
}
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 940adc809535..775ce21656f7 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -146,6 +146,7 @@ public class PasspointConfigurationTest {
*/
private static PasspointConfiguration createConfig() {
PasspointConfiguration config = new PasspointConfiguration();
+ config.setUpdateIdentifier(1234);
config.setHomeSp(createHomeSp());
config.setCredential(createCredential());
config.setPolicy(createPolicy());
@@ -273,18 +274,37 @@ public class PasspointConfigurationTest {
@Test
public void validateDefaultConfig() throws Exception {
PasspointConfiguration config = new PasspointConfiguration();
+
assertFalse(config.validate());
+ assertFalse(config.validateForR2());
}
/**
- * Verify that a configuration contained all fields is valid.
+ * Verify that a configuration containing all fields is valid for R1/R2.
*
* @throws Exception
*/
@Test
public void validateFullConfig() throws Exception {
PasspointConfiguration config = createConfig();
+
+ assertTrue(config.validate());
+ assertTrue(config.validateForR2());
+ }
+
+ /**
+ * Verify that a configuration containing all fields except for UpdateIdentifier is valid for
+ * R1, but invalid for R2.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateFullConfigWithoutUpdateIdentifier() throws Exception {
+ PasspointConfiguration config = createConfig();
+ config.setUpdateIdentifier(Integer.MIN_VALUE);
+
assertTrue(config.validate());
+ assertFalse(config.validateForR2());
}
/**
@@ -296,7 +316,9 @@ public class PasspointConfigurationTest {
public void validateConfigWithoutCredential() throws Exception {
PasspointConfiguration config = createConfig();
config.setCredential(null);
+
assertFalse(config.validate());
+ assertFalse(config.validateForR2());
}
/**
@@ -308,12 +330,14 @@ public class PasspointConfigurationTest {
public void validateConfigWithoutHomeSp() throws Exception {
PasspointConfiguration config = createConfig();
config.setHomeSp(null);
+
assertFalse(config.validate());
+ assertFalse(config.validateForR2());
}
/**
* Verify that a configuration without Policy is valid, since Policy configurations
- * are optional (applied for Hotspot 2.0 Release only).
+ * are optional for R1 and R2.
*
* @throws Exception
*/
@@ -321,12 +345,14 @@ public class PasspointConfigurationTest {
public void validateConfigWithoutPolicy() throws Exception {
PasspointConfiguration config = createConfig();
config.setPolicy(null);
+
assertTrue(config.validate());
+ assertTrue(config.validateForR2());
}
/**
- * Verify that a configuration without subscription update is valid, since subscription
- * update configurations are optional (applied for Hotspot 2.0 Release only).
+ * Verify that a configuration without subscription update is valid for R1 and invalid for R2,
+ * since subscription update configuration is only applicable for R2.
*
* @throws Exception
*/
@@ -334,7 +360,9 @@ public class PasspointConfigurationTest {
public void validateConfigWithoutSubscriptionUpdate() throws Exception {
PasspointConfiguration config = createConfig();
config.setSubscriptionUpdate(null);
+
assertTrue(config.validate());
+ assertFalse(config.validateForR2());
}
/**
@@ -352,12 +380,15 @@ public class PasspointConfigurationTest {
trustRootCertList.put(new String(rawUrlBytes, StandardCharsets.UTF_8),
new byte[CERTIFICATE_FINGERPRINT_BYTES]);
config.setTrustRootCertList(trustRootCertList);
+
assertFalse(config.validate());
trustRootCertList = new HashMap<>();
trustRootCertList.put(null, new byte[CERTIFICATE_FINGERPRINT_BYTES]);
config.setTrustRootCertList(trustRootCertList);
+
assertFalse(config.validate());
+ assertFalse(config.validateForR2());
}
/**
@@ -382,6 +413,7 @@ public class PasspointConfigurationTest {
trustRootCertList.put("test.cert.com", null);
config.setTrustRootCertList(trustRootCertList);
assertFalse(config.validate());
+ assertFalse(config.validateForR2());
}
/**
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
index c5ad7de12d19..c07db6c323a2 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
@@ -24,14 +24,13 @@ import android.net.wifi.FakeKeys;
import android.os.Parcel;
import android.support.test.filters.SmallTest;
+import org.junit.Test;
+
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
-import java.util.Arrays;
-
-import org.junit.Test;
/**
* Unit tests for {@link android.net.wifi.hotspot2.pps.CredentialTest}.
@@ -169,7 +168,12 @@ public class CredentialTest {
@Test
public void validateUserCredential() throws Exception {
Credential cred = createCredentialWithUserCredential();
- assertTrue(cred.validate());
+
+ // For R1 validation
+ assertTrue(cred.validate(true));
+
+ // For R2 validation
+ assertTrue(cred.validate(false));
}
/**
@@ -181,7 +185,12 @@ public class CredentialTest {
public void validateUserCredentialWithoutCaCert() throws Exception {
Credential cred = createCredentialWithUserCredential();
cred.setCaCertificate(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertTrue(cred.validate(false));
}
/**
@@ -193,7 +202,12 @@ public class CredentialTest {
public void validateUserCredentialWithEapTls() throws Exception {
Credential cred = createCredentialWithUserCredential();
cred.getUserCredential().setEapType(EAPConstants.EAP_TLS);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
@@ -206,7 +220,12 @@ public class CredentialTest {
public void validateUserCredentialWithoutRealm() throws Exception {
Credential cred = createCredentialWithUserCredential();
cred.setRealm(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -218,7 +237,12 @@ public class CredentialTest {
public void validateUserCredentialWithoutUsername() throws Exception {
Credential cred = createCredentialWithUserCredential();
cred.getUserCredential().setUsername(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -230,7 +254,12 @@ public class CredentialTest {
public void validateUserCredentialWithoutPassword() throws Exception {
Credential cred = createCredentialWithUserCredential();
cred.getUserCredential().setPassword(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -242,7 +271,12 @@ public class CredentialTest {
public void validateUserCredentialWithoutAuthMethod() throws Exception {
Credential cred = createCredentialWithUserCredential();
cred.getUserCredential().setNonEapInnerMethod(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -255,7 +289,12 @@ public class CredentialTest {
@Test
public void validateCertCredential() throws Exception {
Credential cred = createCredentialWithCertificateCredential();
- assertTrue(cred.validate());
+
+ // For R1 validation
+ assertTrue(cred.validate(true));
+
+ // For R2 validation
+ assertTrue(cred.validate(true));
}
/**
@@ -267,7 +306,12 @@ public class CredentialTest {
public void validateCertCredentialWithoutCaCert() throws Exception {
Credential cred = createCredentialWithCertificateCredential();
cred.setCaCertificate(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertTrue(cred.validate(false));
}
/**
@@ -279,7 +323,12 @@ public class CredentialTest {
public void validateCertCredentialWithoutClientCertChain() throws Exception {
Credential cred = createCredentialWithCertificateCredential();
cred.setClientCertificateChain(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -291,7 +340,12 @@ public class CredentialTest {
public void validateCertCredentialWithoutClientPrivateKey() throws Exception {
Credential cred = createCredentialWithCertificateCredential();
cred.setClientPrivateKey(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -304,7 +358,12 @@ public class CredentialTest {
public void validateCertCredentialWithMismatchFingerprint() throws Exception {
Credential cred = createCredentialWithCertificateCredential();
cred.getCertCredential().setCertSha256Fingerprint(new byte[32]);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -315,7 +374,12 @@ public class CredentialTest {
@Test
public void validateSimCredentialWithEapSim() throws Exception {
Credential cred = createCredentialWithSimCredential();
- assertTrue(cred.validate());
+
+ // For R1 validation
+ assertTrue(cred.validate(true));
+
+ // For R2 validation
+ assertTrue(cred.validate(false));
}
/**
@@ -327,7 +391,12 @@ public class CredentialTest {
public void validateSimCredentialWithEapAka() throws Exception {
Credential cred = createCredentialWithSimCredential();
cred.getSimCredential().setEapType(EAPConstants.EAP_AKA);
- assertTrue(cred.validate());
+
+ // For R1 validation
+ assertTrue(cred.validate(true));
+
+ // For R2 validation
+ assertTrue(cred.validate(false));
}
/**
@@ -339,7 +408,12 @@ public class CredentialTest {
public void validateSimCredentialWithEapAkaPrime() throws Exception {
Credential cred = createCredentialWithSimCredential();
cred.getSimCredential().setEapType(EAPConstants.EAP_AKA_PRIME);
- assertTrue(cred.validate());
+
+ // For R1 validation
+ assertTrue(cred.validate(true));
+
+ // For R2 validation
+ assertTrue(cred.validate(false));
}
/**
@@ -351,7 +425,12 @@ public class CredentialTest {
public void validateSimCredentialWithoutIMSI() throws Exception {
Credential cred = createCredentialWithSimCredential();
cred.getSimCredential().setImsi(null);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -363,7 +442,12 @@ public class CredentialTest {
public void validateSimCredentialWithInvalidIMSI() throws Exception {
Credential cred = createCredentialWithSimCredential();
cred.getSimCredential().setImsi("dummy");
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -375,7 +459,12 @@ public class CredentialTest {
public void validateSimCredentialWithEapTls() throws Exception {
Credential cred = createCredentialWithSimCredential();
cred.getSimCredential().setEapType(EAPConstants.EAP_TLS);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**
@@ -391,7 +480,12 @@ public class CredentialTest {
simCredential.setImsi("1234*");
simCredential.setEapType(EAPConstants.EAP_SIM);
cred.setSimCredential(simCredential);
- assertFalse(cred.validate());
+
+ // For R1 validation
+ assertFalse(cred.validate(true));
+
+ // For R2 validation
+ assertFalse(cred.validate(false));
}
/**