summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CleanSpec.mk1
-rw-r--r--api/test-current.txt1
-rw-r--r--cmds/incident/Android.bp2
-rw-r--r--cmds/incident/main.cpp30
-rw-r--r--cmds/telecom/src/com/android/commands/telecom/Telecom.java89
-rw-r--r--core/java/android/app/ActivityThread.java13
-rw-r--r--core/java/android/app/ActivityView.java11
-rw-r--r--core/java/android/app/IUriGrantsManager.aidl5
-rw-r--r--core/java/android/bluetooth/le/ScanFilter.java8
-rw-r--r--core/java/android/content/ClipboardManager.java19
-rw-r--r--core/java/android/content/ContentResolver.java18
-rw-r--r--core/java/android/content/IClipboard.aidl17
-rw-r--r--core/java/android/content/res/ResourcesImpl.java7
-rw-r--r--core/java/android/net/ConnectivityManager.java22
-rw-r--r--core/java/android/net/StaticIpConfiguration.java6
-rw-r--r--core/java/android/os/Binder.java2
-rw-r--r--core/java/android/os/storage/StorageManagerInternal.java8
-rw-r--r--core/java/android/preference/SeekBarVolumizer.java2
-rw-r--r--core/java/android/provider/DocumentsContract.java50
-rw-r--r--core/java/android/provider/Downloads.java2
-rw-r--r--core/java/android/provider/MediaStore.java2
-rw-r--r--core/java/android/provider/Settings.java15
-rw-r--r--core/java/android/service/autofill/augmented/AugmentedAutofillService.java14
-rw-r--r--core/java/android/service/contentcapture/ContentCaptureService.java4
-rw-r--r--core/java/android/service/quicksettings/Tile.java4
-rw-r--r--core/java/android/service/wallpaper/Android.bp12
-rw-r--r--core/java/android/service/wallpaper/AndroidManifest.xml22
-rw-r--r--core/java/android/text/Emoji.java24
-rw-r--r--core/java/android/util/MemoryIntArray.java10
-rw-r--r--core/java/android/view/RenderNodeAnimator.java2
-rw-r--r--core/java/android/view/SurfaceView.java37
-rw-r--r--core/java/android/view/View.java76
-rw-r--r--core/java/android/view/ViewPropertyAnimator.java5
-rw-r--r--core/java/android/view/autofill/AutofillManager.java11
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureSession.java2
-rw-r--r--core/java/android/view/contentcapture/DataRemovalRequest.java3
-rw-r--r--core/java/android/view/textclassifier/SelectionSessionLogger.java15
-rw-r--r--core/java/android/view/textclassifier/TextClassificationSession.java14
-rw-r--r--core/java/android/widget/TextClock.java12
-rw-r--r--core/java/android/widget/TextView.java31
-rw-r--r--core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java10
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java66
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java44
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBar.aidl5
-rw-r--r--core/java/com/android/internal/widget/ResolverDrawerLayout.java11
-rw-r--r--core/jni/android_graphics_Canvas.cpp6
-rw-r--r--core/proto/android/app/settings_enums.proto6
-rw-r--r--core/res/AndroidManifest.xml6
-rw-r--r--core/res/res/drawable/list_divider_material.xml4
-rw-r--r--core/res/res/values-night/themes_device_defaults.xml5
-rw-r--r--core/res/res/values/attrs.xml4
-rw-r--r--core/res/res/values/colors_device_defaults.xml12
-rw-r--r--core/res/res/values/colors_material.xml3
-rw-r--r--core/res/res/values/config.xml2
-rw-r--r--core/res/res/values/locale_config.xml1
-rw-r--r--core/res/res/values/strings.xml2
-rw-r--r--core/res/res/values/themes_device_defaults.xml16
-rw-r--r--core/res/res/values/themes_material.xml4
-rw-r--r--core/tests/bugreports/src/android/server/bugreports/BugreportManagerTest.java12
-rw-r--r--core/tests/coretests/src/android/text/EmojiTest.java20
-rw-r--r--data/etc/hiddenapi-package-whitelist.xml1
-rw-r--r--data/etc/platform.xml6
-rw-r--r--data/etc/privapp-permissions-platform.xml4
-rw-r--r--graphics/java/android/graphics/Canvas.java13
-rw-r--r--graphics/java/android/graphics/drawable/GradientDrawable.java6
-rw-r--r--libs/androidfw/AssetManager2.cpp2
-rw-r--r--libs/hwui/DisplayListOps.in3
-rw-r--r--libs/hwui/RecordingCanvas.cpp13
-rw-r--r--libs/hwui/RecordingCanvas.h2
-rw-r--r--libs/hwui/SkiaCanvas.cpp13
-rw-r--r--libs/hwui/SkiaCanvas.h1
-rw-r--r--libs/hwui/hwui/Canvas.h1
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.cpp2
-rw-r--r--libs/protoutil/include/android/util/ProtoOutputStream.h2
-rw-r--r--libs/protoutil/src/ProtoOutputStream.cpp18
-rw-r--r--libs/protoutil/tests/ProtoOutputStream_test.cpp47
-rw-r--r--location/java/com/android/internal/location/GpsNetInitiatedHandler.java31
-rw-r--r--media/java/android/media/AudioAttributes.java10
-rw-r--r--media/java/android/media/ThumbnailUtils.java10
-rw-r--r--media/java/android/media/audiopolicy/AudioMix.java57
-rw-r--r--media/java/android/media/audiopolicy/AudioMixingRule.java4
-rw-r--r--packages/BackupRestoreConfirmation/res/values-eu/strings.xml4
-rw-r--r--packages/BackupRestoreConfirmation/res/values-hi/strings.xml6
-rw-r--r--packages/CaptivePortalLogin/res/values-bs/strings.xml2
-rw-r--r--packages/CarSystemUI/res/drawable/notification_handle_bar.xml26
-rw-r--r--packages/CarSystemUI/res/layout/car_ongoing_privacy_chip.xml37
-rw-r--r--packages/CarSystemUI/res/layout/car_top_navigation_bar.xml2
-rw-r--r--packages/CarSystemUI/res/layout/notification_center_activity.xml25
-rw-r--r--packages/CarSystemUI/res/layout/notification_handle_bar.xml30
-rw-r--r--packages/CarSystemUI/res/values/colors.xml2
-rw-r--r--packages/CarSystemUI/res/values/dimens.xml30
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java23
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java228
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java62
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyDialogBuilder.java59
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java46
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyType.java53
-rw-r--r--packages/CtsShim/apk/arm/CtsShim.apkbin4817 -> 4837 bytes
-rw-r--r--packages/CtsShim/apk/arm/CtsShimPriv.apkbin9938 -> 10389 bytes
-rw-r--r--packages/CtsShim/apk/x86/CtsShim.apkbin4817 -> 4837 bytes
-rw-r--r--packages/CtsShim/apk/x86/CtsShimPriv.apkbin10205 -> 10466 bytes
-rw-r--r--packages/DynamicSystemInstallationService/src/com/android/dynsystem/BootCompletedReceiver.java25
-rw-r--r--packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java2
-rw-r--r--packages/ExtServices/src/android/ext/services/notification/Assistant.java59
-rw-r--r--packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImpl.java4
-rw-r--r--packages/ExtServices/tests/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImplTest.java201
-rw-r--r--packages/NetworkStack/Android.bp8
-rw-r--r--packages/NetworkStack/src/com/android/server/NetworkStackService.java40
-rw-r--r--packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java4
-rw-r--r--packages/NetworkStack/tests/unit/Android.bp (renamed from packages/NetworkStack/tests/Android.bp)4
-rw-r--r--packages/NetworkStack/tests/unit/AndroidManifest.xml (renamed from packages/NetworkStack/tests/AndroidManifest.xml)0
-rw-r--r--packages/NetworkStack/tests/unit/AndroidTest.xml (renamed from packages/NetworkStack/tests/AndroidTest.xml)0
-rw-r--r--packages/NetworkStack/tests/unit/jni/apf_jni.cpp (renamed from packages/NetworkStack/tests/jni/apf_jni.cpp)0
-rw-r--r--packages/NetworkStack/tests/unit/res/raw/apf.pcap (renamed from packages/NetworkStack/tests/res/raw/apf.pcap)bin5702 -> 5702 bytes
-rw-r--r--packages/NetworkStack/tests/unit/res/raw/apfPcap.pcap (renamed from packages/NetworkStack/tests/res/raw/apfPcap.pcap)bin101547 -> 101547 bytes
-rw-r--r--packages/NetworkStack/tests/unit/src/android/net/apf/ApfTest.java (renamed from packages/NetworkStack/tests/src/android/net/apf/ApfTest.java)0
-rw-r--r--packages/NetworkStack/tests/unit/src/android/net/apf/Bpf2Apf.java (renamed from packages/NetworkStack/tests/src/android/net/apf/Bpf2Apf.java)0
-rw-r--r--packages/NetworkStack/tests/unit/src/android/net/captiveportal/CaptivePortalProbeSpecTest.java (renamed from packages/NetworkStack/tests/src/android/net/captiveportal/CaptivePortalProbeSpecTest.java)0
-rw-r--r--packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpLeaseRepositoryTest.java (renamed from packages/NetworkStack/tests/src/android/net/dhcp/DhcpLeaseRepositoryTest.java)0
-rw-r--r--packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpPacketTest.java (renamed from packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java)0
-rw-r--r--packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpServerTest.java (renamed from packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java)0
-rw-r--r--packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpServingParamsTest.java (renamed from packages/NetworkStack/tests/src/android/net/dhcp/DhcpServingParamsTest.java)0
-rw-r--r--packages/NetworkStack/tests/unit/src/android/net/ip/IpClientTest.java (renamed from packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java)0
-rw-r--r--packages/NetworkStack/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.java (renamed from packages/NetworkStack/tests/src/android/net/ip/IpReachabilityMonitorTest.java)0
-rw-r--r--packages/NetworkStack/tests/unit/src/android/net/util/ConnectivityPacketSummaryTest.java (renamed from packages/NetworkStack/tests/src/android/net/util/ConnectivityPacketSummaryTest.java)0
-rw-r--r--packages/NetworkStack/tests/unit/src/android/net/util/PacketReaderTest.java (renamed from packages/NetworkStack/tests/src/android/net/util/PacketReaderTest.java)0
-rw-r--r--packages/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java (renamed from packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java)1
-rw-r--r--packages/NetworkStack/tests/unit/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java (renamed from packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java)0
-rw-r--r--packages/NetworkStack/tests/unit/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java (renamed from packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java)0
-rw-r--r--packages/NetworkStack/tests/unit/src/com/android/server/util/SharedLogTest.java (renamed from packages/NetworkStack/tests/src/com/android/server/util/SharedLogTest.java)0
-rw-r--r--packages/PackageInstaller/res/values-bs/strings.xml2
-rw-r--r--packages/PackageInstaller/res/values-eu/strings.xml6
-rw-r--r--packages/PrintSpooler/res/values-fr/strings.xml2
-rw-r--r--packages/PrintSpooler/res/values-hi/strings.xml6
-rw-r--r--packages/PrintSpooler/res/values-my/strings.xml4
-rw-r--r--packages/PrintSpooler/res/values-pl/strings.xml2
-rw-r--r--packages/PrintSpooler/res/values-ta/strings.xml2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/fuelgauge/Estimate.kt12
-rw-r--r--packages/SettingsProvider/res/values/defaults.xml3
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java21
-rw-r--r--packages/Shell/AndroidManifest.xml6
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values/styles.xml1
-rw-r--r--packages/SystemUI/res/drawable-night/status_bar_notification_section_header_clear_btn.xml25
-rw-r--r--packages/SystemUI/res/drawable/corner_gesture_hint.xml25
-rw-r--r--packages/SystemUI/res/drawable/status_bar_notification_section_header_clear_btn.xml2
-rw-r--r--packages/SystemUI/res/layout/bubble_expanded_view.xml5
-rw-r--r--packages/SystemUI/res/layout/contaminant_dialog.xml87
-rw-r--r--packages/SystemUI/res/layout/notification_info.xml6
-rw-r--r--packages/SystemUI/res/layout/qs_customize_header.xml1
-rw-r--r--packages/SystemUI/res/layout/quick_settings_header_info.xml31
-rw-r--r--packages/SystemUI/res/layout/rounded_corners.xml18
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_section_header.xml5
-rw-r--r--packages/SystemUI/res/values-night/colors.xml1
-rw-r--r--packages/SystemUI/res/values/attrs.xml6
-rw-r--r--packages/SystemUI/res/values/colors.xml1
-rw-r--r--packages/SystemUI/res/values/dimens.xml9
-rw-r--r--packages/SystemUI/res/values/strings.xml15
-rw-r--r--packages/SystemUI/res/values/styles.xml18
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl6
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java66
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java33
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java10
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/ImageWallpaper.java220
-rw-r--r--packages/SystemUI/src/com/android/systemui/ScreenDecorations.java90
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistManager.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java62
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java121
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/chooser/ChooserHelper.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java230
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java87
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java72
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java116
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java57
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSHeaderInfoLayout.kt131
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java59
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java21
-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.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java67
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java47
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/UsbContaminantActivity.java50
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/ResourceIconTest.kt41
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java54
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java39
-rw-r--r--packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-km/strings.xml2
-rw-r--r--packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-km/strings.xml2
-rw-r--r--packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-km/strings.xml2
-rw-r--r--packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-km/strings.xml2
-rw-r--r--packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-km/strings.xml2
-rw-r--r--proto/src/metrics_constants/metrics_constants.proto11
-rw-r--r--services/art-profile2
-rw-r--r--services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java14
-rw-r--r--services/core/Android.bp4
-rw-r--r--services/core/java/com/android/server/DynamicSystemService.java13
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java66
-rw-r--r--services/core/java/com/android/server/SystemServerInitThreadPool.java3
-rw-r--r--services/core/java/com/android/server/Watchdog.java10
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerConstants.java4
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java16
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java28
-rw-r--r--services/core/java/com/android/server/attention/AttentionManagerService.java12
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java90
-rw-r--r--services/core/java/com/android/server/camera/CameraServiceProxy.java49
-rw-r--r--services/core/java/com/android/server/clipboard/ClipboardService.java239
-rw-r--r--services/core/java/com/android/server/content/SyncManager.java2
-rw-r--r--services/core/java/com/android/server/content/SyncStorageEngine.java10
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java14
-rw-r--r--services/core/java/com/android/server/location/GnssConfiguration.java9
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java5
-rw-r--r--services/core/java/com/android/server/location/GnssVisibilityControl.java263
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java10
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java72
-rw-r--r--services/core/java/com/android/server/pm/ModuleInfoProvider.java18
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java29
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java25
-rw-r--r--services/core/java/com/android/server/pm/permission/TEST_MAPPING35
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyInternal.java3
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyService.java35
-rw-r--r--services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java14
-rw-r--r--services/core/java/com/android/server/rollback/TEST_MAPPING8
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java5
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java12
-rw-r--r--services/core/java/com/android/server/uri/UriGrantsManagerService.java12
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java28
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java19
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java10
-rw-r--r--services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java75
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimationController.java9
-rw-r--r--services/core/java/com/android/server/wm/RefreshRatePolicy.java92
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerInternal.java14
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java18
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java5
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java2
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java12
-rw-r--r--services/java/com/android/server/SystemServer.java7
-rw-r--r--services/net/Android.bp9
-rw-r--r--services/net/aidl/ipmemorystore/3/android/net/IIpMemoryStore.aidl10
-rw-r--r--services/net/aidl/ipmemorystore/3/android/net/IIpMemoryStoreCallbacks.aidl4
-rw-r--r--services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/Blob.aidl4
-rw-r--r--services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl4
-rw-r--r--services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl4
-rw-r--r--services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl4
-rw-r--r--services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl4
-rw-r--r--services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnStatusListener.aidl4
-rw-r--r--services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/NetworkAttributesParcelable.aidl8
-rw-r--r--services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl6
-rw-r--r--services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/StatusParcelable.aidl4
-rw-r--r--services/net/java/android/net/IIpMemoryStore.aidl5
-rw-r--r--services/tests/servicestests/Android.bp2
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java29
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java17
-rw-r--r--services/tests/uiservicestests/Android.bp2
-rw-r--r--services/tests/uiservicestests/AndroidManifest.xml2
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java208
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java66
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java22
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java86
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java130
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java22
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java1
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java2
-rw-r--r--telecomm/java/android/telecom/ConnectionService.java4
-rw-r--r--telecomm/java/android/telecom/ConnectionServiceAdapter.java4
-rw-r--r--telecomm/java/android/telecom/ConnectionServiceAdapterServant.java14
-rw-r--r--telecomm/java/android/telecom/RemoteConnectionService.java2
-rw-r--r--telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl3
-rwxr-xr-xtelephony/java/android/telephony/CarrierConfigManager.java9
-rw-r--r--telephony/java/android/telephony/SubscriptionInfo.java2
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java20
-rw-r--r--telephony/java/android/telephony/ims/ImsSsInfo.java4
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl7
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyPermissions.java10
-rw-r--r--tests/RollbackTest/Android.bp42
-rw-r--r--tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java232
-rw-r--r--tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java78
-rw-r--r--tests/RollbackTest/TestApex/RollbackTestApex.prebuilt.txt3
-rw-r--r--tests/RollbackTest/TestApex/RollbackTestApexV1.json4
-rw-r--r--tests/RollbackTest/TestApex/RollbackTestApexV2.json4
-rw-r--r--tests/RollbackTest/TestApex/RollbackTestApexV3.json4
-rw-r--r--tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.avbpubkeybin1032 -> 0 bytes
-rw-r--r--tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.pem51
-rw-r--r--tests/net/Android.bp2
-rw-r--r--tools/incident_report/main.cpp13
314 files changed, 5060 insertions, 2059 deletions
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 7c21875d685f..f311fc81fc10 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -252,6 +252,7 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/SystemUI)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/DynamicAndroidInstallationService)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/DefaultContainerService)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/CaptivePortalLogin)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
# ******************************************************************
diff --git a/api/test-current.txt b/api/test-current.txt
index 0de0d7503391..b1ffbad822b7 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3171,6 +3171,7 @@ package android.view {
@UiThread public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
method public android.view.View getTooltipView();
+ method public boolean isAutofilled();
method public static boolean isDefaultFocusHighlightEnabled();
method public boolean isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
method protected void resetResolvedDrawables();
diff --git a/cmds/incident/Android.bp b/cmds/incident/Android.bp
index f56f101465eb..9e9dac14c802 100644
--- a/cmds/incident/Android.bp
+++ b/cmds/incident/Android.bp
@@ -30,7 +30,7 @@ cc_binary {
],
static_libs: [
- "libplatformprotos",
+ "libprotoutil",
],
cflags: [
diff --git a/cmds/incident/main.cpp b/cmds/incident/main.cpp
index eca781fd4e4f..dfb4f994b866 100644
--- a/cmds/incident/main.cpp
+++ b/cmds/incident/main.cpp
@@ -21,6 +21,7 @@
#include <android/os/BnIncidentReportStatusListener.h>
#include <android/os/IIncidentManager.h>
#include <android/os/IncidentReportArgs.h>
+#include <android/util/ProtoOutputStream.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <utils/Looper.h>
@@ -36,6 +37,9 @@ using namespace android;
using namespace android::base;
using namespace android::binder;
using namespace android::os;
+using android::util::FIELD_COUNT_SINGLE;
+using android::util::FIELD_TYPE_STRING;
+using android::util::ProtoOutputStream;
// ================================================================================
class StatusListener : public BnIncidentReportStatusListener {
@@ -129,11 +133,11 @@ static void section_list(FILE* out) {
static IncidentSection const*
find_section(const char* name)
{
- size_t low = 0;
- size_t high = INCIDENT_SECTION_COUNT - 1;
+ ssize_t low = 0;
+ ssize_t high = INCIDENT_SECTION_COUNT - 1;
while (low <= high) {
- size_t mid = (low + high) >> 1;
+ ssize_t mid = (low + high) / 2;
IncidentSection const* section = INCIDENT_SECTIONS + mid;
int cmp = strcmp(section->name, name);
@@ -208,6 +212,7 @@ usage(FILE* out)
fprintf(out, "and one of these destinations:\n");
fprintf(out, " -b (default) print the report to stdout (in proto format)\n");
fprintf(out, " -d send the report into dropbox\n");
+ fprintf(out, " -r REASON human readable description of why the report is taken.\n");
fprintf(out, " -s PKG/CLS send broadcast to the broadcast receiver.\n");
fprintf(out, "\n");
fprintf(out, " SECTION the field numbers of the incident report fields to include\n");
@@ -221,11 +226,12 @@ main(int argc, char** argv)
IncidentReportArgs args;
enum { DEST_UNSET, DEST_DROPBOX, DEST_STDOUT, DEST_BROADCAST } destination = DEST_UNSET;
int privacyPolicy = PRIVACY_POLICY_AUTOMATIC;
+ string reason;
string receiverArg;
// Parse the args
int opt;
- while ((opt = getopt(argc, argv, "bhdlp:s:")) != -1) {
+ while ((opt = getopt(argc, argv, "bhdlp:r:s:")) != -1) {
switch (opt) {
case 'h':
usage(stdout);
@@ -250,6 +256,13 @@ main(int argc, char** argv)
case 'p':
privacyPolicy = get_privacy_policy(optarg);
break;
+ case 'r':
+ if (reason.size() > 0) {
+ usage(stderr);
+ return 1;
+ }
+ reason = optarg;
+ break;
case 's':
if (destination != DEST_UNSET) {
usage(stderr);
@@ -291,6 +304,7 @@ main(int argc, char** argv)
} else {
IncidentSection const* ic = find_section(arg);
if (ic == NULL) {
+ ALOGD("Invalid section: %s\n", arg);
fprintf(stderr, "Invalid section: %s\n", arg);
return 1;
}
@@ -301,6 +315,14 @@ main(int argc, char** argv)
}
args.setPrivacyPolicy(privacyPolicy);
+ if (reason.size() > 0) {
+ ProtoOutputStream proto;
+ proto.write(/* reason field id */ 2 | FIELD_TYPE_STRING | FIELD_COUNT_SINGLE, reason);
+ vector<uint8_t> header;
+ proto.serializeToVector(&header);
+ args.addHeader(header);
+ }
+
// Start the thread pool.
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
diff --git a/cmds/telecom/src/com/android/commands/telecom/Telecom.java b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
index 052445095afe..e0f7d862e70a 100644
--- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java
+++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
@@ -20,16 +20,21 @@ import android.content.ComponentName;
import android.content.Context;
import android.net.Uri;
import android.os.IUserManager;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.telecom.Log;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
+import android.telephony.TelephonyManager;
import android.text.TextUtils;
import com.android.internal.os.BaseCommand;
import com.android.internal.telecom.ITelecomService;
+import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.TelephonyProperties;
import java.io.PrintStream;
@@ -62,10 +67,14 @@ public final class Telecom extends BaseCommand {
private static final String COMMAND_GET_DEFAULT_DIALER = "get-default-dialer";
private static final String COMMAND_GET_SYSTEM_DIALER = "get-system-dialer";
private static final String COMMAND_WAIT_ON_HANDLERS = "wait-on-handlers";
+ private static final String COMMAND_SET_SIM_COUNT = "set-sim-count";
+ private static final String COMMAND_GET_SIM_CONFIG = "get-sim-config";
+ private static final String COMMAND_GET_MAX_PHONES = "get-max-phones";
private ComponentName mComponent;
private String mAccountId;
private ITelecomService mTelecomService;
+ private ITelephony mTelephonyService;
private IUserManager mUserManager;
@Override
@@ -88,21 +97,32 @@ public final class Telecom extends BaseCommand {
+ "usage: telecom get-default-dialer\n"
+ "usage: telecom get-system-dialer\n"
+ "usage: telecom wait-on-handlers\n"
+ + "usage: telecom set-sim-count <COUNT>\n"
+ + "usage: telecom get-sim-config\n"
+ + "usage: telecom get-max-phones\n"
+ "\n"
- + "telecom set-phone-account-enabled: Enables the given phone account, if it has \n"
- + " already been registered with Telecom.\n"
+ + "telecom set-phone-account-enabled: Enables the given phone account, if it has"
+ + " already been registered with Telecom.\n"
+ "\n"
- + "telecom set-phone-account-disabled: Disables the given phone account, if it \n"
- + " has already been registered with telecom.\n"
+ + "telecom set-phone-account-disabled: Disables the given phone account, if it"
+ + " has already been registered with telecom.\n"
+ "\n"
- + "telecom set-default-dialer: Sets the override default dialer to the given "
- + "component; this will override whatever the dialer role is set to. \n"
+ + "telecom set-default-dialer: Sets the override default dialer to the given"
+ + " component; this will override whatever the dialer role is set to.\n"
+ "\n"
- + "telecom get-default-dialer: Displays the current default dialer. \n"
+ + "telecom get-default-dialer: Displays the current default dialer.\n"
+ "\n"
- + "telecom get-system-dialer: Displays the current system dialer. \n"
+ + "telecom get-system-dialer: Displays the current system dialer.\n"
+ "\n"
- + "telecom wait-on-handlers: Wait until all handlers finish their work. \n"
+ + "telecom wait-on-handlers: Wait until all handlers finish their work.\n"
+ + "\n"
+ + "telecom set-sim-count: Set num SIMs (2 for DSDS, 1 for single SIM."
+ + " This may restart the device.\n"
+ + "\n"
+ + "telecom get-sim-config: Get the mSIM config string. \"DSDS\" for DSDS mode,"
+ + " or \"\" for single SIM\n"
+ + "\n"
+ + "telecom get-max-phones: Get the max supported phones from the modem.\n"
);
}
@@ -115,6 +135,15 @@ public final class Telecom extends BaseCommand {
showError("Error: Could not access the Telecom Manager. Is the system running?");
return;
}
+
+ mTelephonyService = ITelephony.Stub.asInterface(
+ ServiceManager.getService(Context.TELEPHONY_SERVICE));
+ if (mTelephonyService == null) {
+ Log.w(this, "onRun: Can't access telephony service.");
+ showError("Error: Could not access the Telephony Service. Is the system running?");
+ return;
+ }
+
mUserManager = IUserManager.Stub
.asInterface(ServiceManager.getService(Context.USER_SERVICE));
if (mUserManager == null) {
@@ -170,6 +199,15 @@ public final class Telecom extends BaseCommand {
case COMMAND_WAIT_ON_HANDLERS:
runWaitOnHandler();
break;
+ case COMMAND_SET_SIM_COUNT:
+ runSetSimCount();
+ break;
+ case COMMAND_GET_SIM_CONFIG:
+ runGetSimConfig();
+ break;
+ case COMMAND_GET_MAX_PHONES:
+ runGetMaxPhones();
+ break;
default:
Log.w(this, "onRun: unknown command: %s", command);
throw new IllegalArgumentException ("unknown command '" + command + "'");
@@ -271,6 +309,35 @@ public final class Telecom extends BaseCommand {
}
+ private void runSetSimCount() throws RemoteException {
+ if (!callerIsRoot()) {
+ System.out.println("set-sim-count requires adb root");
+ return;
+ }
+ int numSims = Integer.parseInt(nextArgRequired());
+ System.out.println("Setting sim count to " + numSims + ". Device may reboot");
+ mTelephonyService.switchMultiSimConfig(numSims);
+ }
+
+ /**
+ * Prints the mSIM config to the console.
+ * "DSDS" for a phone in DSDS mode
+ * "" (empty string) for a phone in SS mode
+ */
+ private void runGetSimConfig() throws RemoteException {
+ System.out.println(SystemProperties.get(TelephonyProperties.PROPERTY_MULTI_SIM_CONFIG));
+ }
+
+ private void runGetMaxPhones() throws RemoteException {
+ // This assumes the max number of SIMs is 2, which it currently is
+ if (TelephonyManager.MULTISIM_ALLOWED
+ == mTelephonyService.isMultiSimSupported("com.android.commands.telecom")) {
+ System.out.println("2");
+ } else {
+ System.out.println("1");
+ }
+ }
+
private PhoneAccountHandle getPhoneAccountHandleFromArgs() throws RemoteException {
if (TextUtils.isEmpty(mArgs.peekNextArg())) {
return null;
@@ -289,6 +356,10 @@ public final class Telecom extends BaseCommand {
return new PhoneAccountHandle(component, accountId, userHandle);
}
+ private boolean callerIsRoot() {
+ return Process.ROOT_UID == Process.myUid();
+ }
+
private ComponentName parseComponentName(String component) {
ComponentName cn = ComponentName.unflattenFromString(component);
if (cn == null) {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index ca04536af4c0..2db1bcc0faad 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -123,7 +123,6 @@ import android.provider.Settings;
import android.renderscript.RenderScriptCacheDir;
import android.security.NetworkSecurityPolicy;
import android.security.net.config.NetworkSecurityConfigProvider;
-import android.service.voice.VoiceInteractionSession;
import android.system.ErrnoException;
import android.system.OsConstants;
import android.system.StructStat;
@@ -3555,11 +3554,13 @@ public final class ActivityThread extends ClientTransactionHandler {
@NonNull RemoteCallback callback) {
final ActivityClientRecord r = mActivities.get(activityToken);
if (r == null) {
+ Log.w(TAG, "requestDirectActions(): no activity for " + activityToken);
callback.sendResult(null);
return;
}
final int lifecycleState = r.getLifecycleState();
if (lifecycleState < ON_START || lifecycleState >= ON_STOP) {
+ Log.w(TAG, "requestDirectActions(" + r + "): wrong lifecycle: " + lifecycleState);
callback.sendResult(null);
return;
}
@@ -5627,6 +5628,16 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
+ /**
+ * Updates the application info.
+ *
+ * This only works in the system process. Must be called on the main thread.
+ */
+ public void handleSystemApplicationInfoChanged(@NonNull ApplicationInfo ai) {
+ Preconditions.checkState(mSystemThread, "Must only be called in the system process");
+ handleApplicationInfoChanged(ai);
+ }
+
@VisibleForTesting(visibility = PACKAGE)
public void handleApplicationInfoChanged(@NonNull final ApplicationInfo ai) {
// Updates triggered by package installation go through a package update
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 864af8c60b32..4771f9f6ad04 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -189,6 +189,17 @@ public class ActivityView extends ViewGroup {
}
/**
+ * Sets the corner radius for the Activity displayed here. The corners will be
+ * cropped from the window painted by the contained Activity.
+ *
+ * @param cornerRadius the radius for the corners, in pixels
+ * @hide
+ */
+ public void setCornerRadius(float cornerRadius) {
+ mSurfaceView.setCornerRadius(cornerRadius);
+ }
+
+ /**
* Launch a new activity into this container.
* <p>Activity resolved by the provided {@link Intent} must have
* {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be
diff --git a/core/java/android/app/IUriGrantsManager.aidl b/core/java/android/app/IUriGrantsManager.aidl
index 928c627d3f46..9e7f2fecfea0 100644
--- a/core/java/android/app/IUriGrantsManager.aidl
+++ b/core/java/android/app/IUriGrantsManager.aidl
@@ -31,11 +31,12 @@ interface IUriGrantsManager {
in Uri uri, int mode, int sourceUserId, int targetUserId);
/**
* Gets the URI permissions granted to an arbitrary package (or all packages if null)
- * NOTE: this is different from getPersistedUriPermissions(), which returns the URIs the package
+ * NOTE: this is different from getUriPermissions(), which returns the URIs the package
* granted to another packages (instead of those granted to it).
*/
ParceledListSlice getGrantedUriPermissions(in String packageName, int userId);
/** Clears the URI permissions granted to an arbitrary package. */
void clearGrantedUriPermissions(in String packageName, int userId);
- ParceledListSlice getPersistedUriPermissions(in String packageName, boolean incoming);
+ ParceledListSlice getUriPermissions(in String packageName, boolean incoming,
+ boolean persistedOnly);
}
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index 07ba2c6680a9..038994fb5535 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -590,6 +590,9 @@ public final class ScanFilter implements Parcelable {
public @NonNull Builder setServiceSolicitationUuid(
@Nullable ParcelUuid serviceSolicitationUuid) {
mServiceSolicitationUuid = serviceSolicitationUuid;
+ if (serviceSolicitationUuid == null) {
+ mServiceSolicitationUuidMask = null;
+ }
return this;
}
@@ -600,13 +603,16 @@ public final class ScanFilter implements Parcelable {
* indicate a match is needed for the bit in {@code serviceSolicitationUuid}, and 0 to
* ignore that bit.
*
+ * @param serviceSolicitationUuid can only be null if solicitationUuidMask is null.
+ * @param solicitationUuidMask can be null or a mask with no restriction.
+ *
* @throws IllegalArgumentException If {@code serviceSolicitationUuid} is {@code null} but
* {@code serviceSolicitationUuidMask} is not {@code null}.
*/
public @NonNull Builder setServiceSolicitationUuid(
@Nullable ParcelUuid serviceSolicitationUuid,
@Nullable ParcelUuid solicitationUuidMask) {
- if (mServiceSolicitationUuidMask != null && mServiceSolicitationUuid == null) {
+ if (solicitationUuidMask != null && serviceSolicitationUuid == null) {
throw new IllegalArgumentException(
"SolicitationUuid is null while SolicitationUuidMask is not null!");
}
diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java
index 8760efeafd8c..dc1c700f5d08 100644
--- a/core/java/android/content/ClipboardManager.java
+++ b/core/java/android/content/ClipboardManager.java
@@ -103,7 +103,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
try {
Preconditions.checkNotNull(clip);
clip.prepareToLeaveProcess(true);
- mService.setPrimaryClip(clip, mContext.getOpPackageName());
+ mService.setPrimaryClip(clip, mContext.getOpPackageName(), mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -116,7 +116,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
*/
public void clearPrimaryClip() {
try {
- mService.clearPrimaryClip(mContext.getOpPackageName());
+ mService.clearPrimaryClip(mContext.getOpPackageName(), mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -132,7 +132,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
*/
public @Nullable ClipData getPrimaryClip() {
try {
- return mService.getPrimaryClip(mContext.getOpPackageName());
+ return mService.getPrimaryClip(mContext.getOpPackageName(), mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -149,7 +149,8 @@ public class ClipboardManager extends android.text.ClipboardManager {
*/
public @Nullable ClipDescription getPrimaryClipDescription() {
try {
- return mService.getPrimaryClipDescription(mContext.getOpPackageName());
+ return mService.getPrimaryClipDescription(mContext.getOpPackageName(),
+ mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -163,7 +164,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
*/
public boolean hasPrimaryClip() {
try {
- return mService.hasPrimaryClip(mContext.getOpPackageName());
+ return mService.hasPrimaryClip(mContext.getOpPackageName(), mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -174,7 +175,8 @@ public class ClipboardManager extends android.text.ClipboardManager {
if (mPrimaryClipChangedListeners.isEmpty()) {
try {
mService.addPrimaryClipChangedListener(
- mPrimaryClipChangedServiceListener, mContext.getOpPackageName());
+ mPrimaryClipChangedServiceListener, mContext.getOpPackageName(),
+ mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -189,7 +191,8 @@ public class ClipboardManager extends android.text.ClipboardManager {
if (mPrimaryClipChangedListeners.isEmpty()) {
try {
mService.removePrimaryClipChangedListener(
- mPrimaryClipChangedServiceListener);
+ mPrimaryClipChangedServiceListener, mContext.getOpPackageName(),
+ mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -226,7 +229,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
@Deprecated
public boolean hasText() {
try {
- return mService.hasClipboardText(mContext.getOpPackageName());
+ return mService.hasClipboardText(mContext.getOpPackageName(), mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 2c5860ac8775..0a1bc85202ff 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -2482,8 +2482,8 @@ public abstract class ContentResolver implements ContentInterface {
*/
public @NonNull List<UriPermission> getPersistedUriPermissions() {
try {
- return UriGrantsManager.getService()
- .getPersistedUriPermissions(mPackageName, true).getList();
+ return UriGrantsManager.getService().getUriPermissions(
+ mPackageName, true /* incoming */, true /* persistedOnly */).getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2498,8 +2498,18 @@ public abstract class ContentResolver implements ContentInterface {
*/
public @NonNull List<UriPermission> getOutgoingPersistedUriPermissions() {
try {
- return UriGrantsManager.getService()
- .getPersistedUriPermissions(mPackageName, false).getList();
+ return UriGrantsManager.getService().getUriPermissions(
+ mPackageName, false /* incoming */, true /* persistedOnly */).getList();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /** @hide */
+ public @NonNull List<UriPermission> getOutgoingUriPermissions() {
+ try {
+ return UriGrantsManager.getService().getUriPermissions(
+ mPackageName, false /* incoming */, false /* persistedOnly */).getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/content/IClipboard.aidl b/core/java/android/content/IClipboard.aidl
index 135a4363ef21..0d5a46016f19 100644
--- a/core/java/android/content/IClipboard.aidl
+++ b/core/java/android/content/IClipboard.aidl
@@ -26,17 +26,18 @@ import android.content.IOnPrimaryClipChangedListener;
* {@hide}
*/
interface IClipboard {
- void setPrimaryClip(in ClipData clip, String callingPackage);
- void clearPrimaryClip(String callingPackage);
- ClipData getPrimaryClip(String pkg);
- ClipDescription getPrimaryClipDescription(String callingPackage);
- boolean hasPrimaryClip(String callingPackage);
+ void setPrimaryClip(in ClipData clip, String callingPackage, int userId);
+ void clearPrimaryClip(String callingPackage, int userId);
+ ClipData getPrimaryClip(String pkg, int userId);
+ ClipDescription getPrimaryClipDescription(String callingPackage, int userId);
+ boolean hasPrimaryClip(String callingPackage, int userId);
void addPrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener,
- String callingPackage);
- void removePrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener);
+ String callingPackage, int userId);
+ void removePrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener,
+ String callingPackage, int userId);
/**
* Returns true if the clipboard contains text; false otherwise.
*/
- boolean hasClipboardText(String callingPackage);
+ boolean hasClipboardText(String callingPackage, int userId);
}
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 633966c38786..794be9e202be 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -1390,11 +1390,9 @@ public class ResourcesImpl {
@StyleableRes int[] attrs,
@AttrRes int defStyleAttr,
@StyleRes int defStyleRes) {
- Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "obtainStyledAttributes");
- TypedArray array;
synchronized (mKey) {
final int len = attrs.length;
- array = TypedArray.obtain(wrapper.getResources(), len);
+ final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
// XXX note that for now we only work with compiled XML files.
// To support generic XML files we will need to manually parse
@@ -1405,9 +1403,8 @@ public class ResourcesImpl {
array.mDataAddress, array.mIndicesAddress);
array.mTheme = wrapper;
array.mXml = parser;
+ return array;
}
- Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
- return array;
}
@NonNull
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index a69ca99500d6..3bc40a79997f 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3612,8 +3612,9 @@ public class ConnectivityManager {
* @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
* the callback must not be shared - it uniquely specifies this request.
* The callback is invoked on the default internal Handler.
- * @throws IllegalArgumentException if {@code request} specifies any mutable
- * {@code NetworkCapabilities}.
+ * @throws IllegalArgumentException if {@code request} contains invalid network capabilities.
+ * @throws SecurityException if missing the appropriate permissions.
+ * @throws RuntimeException if request limit per UID is exceeded.
*/
public void requestNetwork(@NonNull NetworkRequest request,
@NonNull NetworkCallback networkCallback) {
@@ -3648,8 +3649,9 @@ public class ConnectivityManager {
* @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
* the callback must not be shared - it uniquely specifies this request.
* @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
- * @throws IllegalArgumentException if {@code request} specifies any mutable
- * {@code NetworkCapabilities}.
+ * @throws IllegalArgumentException if {@code request} contains invalid network capabilities.
+ * @throws SecurityException if missing the appropriate permissions.
+ * @throws RuntimeException if request limit per UID is exceeded.
*/
public void requestNetwork(@NonNull NetworkRequest request,
@NonNull NetworkCallback networkCallback, @NonNull Handler handler) {
@@ -3685,6 +3687,9 @@ public class ConnectivityManager {
* @param timeoutMs The time in milliseconds to attempt looking for a suitable network
* before {@link NetworkCallback#onUnavailable()} is called. The timeout must
* be a positive value (i.e. >0).
+ * @throws IllegalArgumentException if {@code request} contains invalid network capabilities.
+ * @throws SecurityException if missing the appropriate permissions.
+ * @throws RuntimeException if request limit per UID is exceeded.
*/
public void requestNetwork(@NonNull NetworkRequest request,
@NonNull NetworkCallback networkCallback, int timeoutMs) {
@@ -3719,6 +3724,9 @@ public class ConnectivityManager {
* @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
* @param timeoutMs The time in milliseconds to attempt looking for a suitable network
* before {@link NetworkCallback#onUnavailable} is called.
+ * @throws IllegalArgumentException if {@code request} contains invalid network capabilities.
+ * @throws SecurityException if missing the appropriate permissions.
+ * @throws RuntimeException if request limit per UID is exceeded.
*/
public void requestNetwork(@NonNull NetworkRequest request,
@NonNull NetworkCallback networkCallback, @NonNull Handler handler, int timeoutMs) {
@@ -3789,9 +3797,9 @@ public class ConnectivityManager {
* @param operation Action to perform when the network is available (corresponds
* to the {@link NetworkCallback#onAvailable} call. Typically
* comes from {@link PendingIntent#getBroadcast}. Cannot be null.
- * @throws IllegalArgumentException if {@code request} contains either
- * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} or
- * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}.
+ * @throws IllegalArgumentException if {@code request} contains invalid network capabilities.
+ * @throws SecurityException if missing the appropriate permissions.
+ * @throws RuntimeException if request limit per UID is exceeded.
*/
public void requestNetwork(@NonNull NetworkRequest request,
@NonNull PendingIntent operation) {
diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java
index 87f8739a5b8f..fe42111afbad 100644
--- a/core/java/android/net/StaticIpConfiguration.java
+++ b/core/java/android/net/StaticIpConfiguration.java
@@ -58,15 +58,15 @@ public final class StaticIpConfiguration implements Parcelable {
@Nullable
public LinkAddress ipAddress;
/** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
@Nullable
public InetAddress gateway;
/** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
@NonNull
public final ArrayList<InetAddress> dnsServers;
/** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UnsupportedAppUsage
@Nullable
public String domains;
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 66ddf21790fe..6178b2bf5817 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -1033,6 +1033,8 @@ public class Binder implements IBinder {
Log.w(TAG, "Caught a RuntimeException from the binder stub implementation.", e);
}
} else {
+ // Clear the parcel before writing the exception
+ reply.setDataSize(0);
reply.setDataPosition(0);
reply.writeException(e);
}
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index 942bf94b1db6..14c299d11a94 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -16,6 +16,7 @@
package android.os.storage;
+import android.annotation.Nullable;
import android.os.IVold;
/**
@@ -101,4 +102,11 @@ public abstract class StorageManagerInternal {
* @param listener The listener that will be notified on reset events.
*/
public abstract void addResetListener(ResetListener listener);
+
+ /**
+ * Notified when any app op changes so that storage mount points can be updated if the app op
+ * affects them.
+ */
+ public abstract void onAppOpsChanged(int code, int uid,
+ @Nullable String packageName, int mode);
}
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 02f99258395c..2b3a2ab05e82 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -591,7 +591,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
private void registerVolumeGroupCb() {
if (mVolumeGroupId != AudioVolumeGroup.DEFAULT_VOLUME_GROUP) {
mAudioManager.registerVolumeGroupCallback(Runnable::run, mVolumeGroupCallback);
- mLastProgress = mAudioManager.getVolumeIndexForAttributes(mAttributes);
+ updateSlider();
}
}
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 22ce39d1784a..fd81178d2cfb 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -36,7 +36,6 @@ import android.graphics.Bitmap;
import android.graphics.ImageDecoder;
import android.graphics.Point;
import android.media.ExifInterface;
-import android.media.MediaFile;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -1681,46 +1680,35 @@ public final class DocumentsContract {
public static AssetFileDescriptor openImageThumbnail(File file) throws FileNotFoundException {
final ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
file, ParcelFileDescriptor.MODE_READ_ONLY);
- Bundle extras = null;
-
try {
final ExifInterface exif = new ExifInterface(file.getAbsolutePath());
- switch (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1)) {
- case ExifInterface.ORIENTATION_ROTATE_90:
- extras = new Bundle(1);
- extras.putInt(EXTRA_ORIENTATION, 90);
- break;
- case ExifInterface.ORIENTATION_ROTATE_180:
- extras = new Bundle(1);
- extras.putInt(EXTRA_ORIENTATION, 180);
- break;
- case ExifInterface.ORIENTATION_ROTATE_270:
- extras = new Bundle(1);
- extras.putInt(EXTRA_ORIENTATION, 270);
- break;
- }
-
final long[] thumb = exif.getThumbnailRange();
if (thumb != null) {
+ // If we use thumb to decode, we need to handle the rotation by ourselves.
+ Bundle extras = null;
+ switch (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1)) {
+ case ExifInterface.ORIENTATION_ROTATE_90:
+ extras = new Bundle(1);
+ extras.putInt(EXTRA_ORIENTATION, 90);
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_180:
+ extras = new Bundle(1);
+ extras.putInt(EXTRA_ORIENTATION, 180);
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_270:
+ extras = new Bundle(1);
+ extras.putInt(EXTRA_ORIENTATION, 270);
+ break;
+ }
+
return new AssetFileDescriptor(pfd, thumb[0], thumb[1], extras);
}
} catch (IOException e) {
}
- // Use ImageDecoder to do full image decode of heif format file
- // will have right orientation. So, we don't need to add orientation
- // information into extras.
- final String mimeType = MediaFile.getMimeTypeForFile(file.getName());
- if (mimeType.equals("image/heif")
- || mimeType.equals("image/heif-sequence")
- || mimeType.equals("image/heic")
- || mimeType.equals("image/heic-sequence")) {
- return new AssetFileDescriptor(pfd, 0 /* startOffset */,
- AssetFileDescriptor.UNKNOWN_LENGTH, null /* extras */);
- }
-
- return new AssetFileDescriptor(pfd, 0, AssetFileDescriptor.UNKNOWN_LENGTH, extras);
+ // Do full file decoding, we don't need to handle the orientation
+ return new AssetFileDescriptor(pfd, 0, AssetFileDescriptor.UNKNOWN_LENGTH, null);
}
private static void rethrowIfNecessary(Exception e) throws FileNotFoundException {
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index d507447c45fa..9a384c6d9d79 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -849,6 +849,8 @@ public final class Downloads {
public static final String CALL_MEDIASTORE_DOWNLOADS_DELETED = "mediastore_downloads_deleted";
/** @hide */
public static final String CALL_CREATE_EXTERNAL_PUBLIC_DIR = "create_external_public_dir";
+ /** @hide */
+ public static final String CALL_REVOKE_MEDIASTORE_URI_PERMS = "revoke_mediastore_uri_perms";
/** @hide */
public static final String EXTRA_IDS = "ids";
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 23937d6c85a6..2a590ce5a65e 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -1077,7 +1077,7 @@ public final class MediaStore {
* Relative path of this media item within the storage device where it
* is persisted. For example, an item stored at
* {@code /storage/0000-0000/DCIM/Vacation/IMG1024.JPG} would have a
- * path of {@code DCIM/Vacation}.
+ * path of {@code DCIM/Vacation/}.
* <p>
* This value should only be used for organizational purposes, and you
* should not attempt to construct or access a raw filesystem path using
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 185d4a219556..8096eb110a1c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8836,6 +8836,15 @@ public final class Settings {
public static final String AWARE_ENABLED = "aware_enabled";
private static final Validator AWARE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
+ /**
+ * Controls whether aware_lock is enabled.
+ * @hide
+ */
+ public static final String AWARE_LOCK_ENABLED = "aware_lock_enabled";
+
+ private static final Validator AWARE_LOCK_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
/**
* This are the settings to be backed up.
*
@@ -8970,7 +8979,8 @@ public final class Settings {
SILENCE_CALL_GESTURE_COUNT,
SILENCE_TIMER_GESTURE_COUNT,
DARK_MODE_DIALOG_SEEN,
- GLOBAL_ACTIONS_PANEL_ENABLED
+ GLOBAL_ACTIONS_PANEL_ENABLED,
+ AWARE_LOCK_ENABLED
};
/**
@@ -9157,6 +9167,7 @@ public final class Settings {
VALIDATORS.put(DARK_MODE_DIALOG_SEEN, BOOLEAN_VALIDATOR);
VALIDATORS.put(UI_NIGHT_MODE, UI_NIGHT_MODE_VALIDATOR);
VALIDATORS.put(GLOBAL_ACTIONS_PANEL_ENABLED, GLOBAL_ACTIONS_PANEL_ENABLED_VALIDATOR);
+ VALIDATORS.put(AWARE_LOCK_ENABLED, AWARE_LOCK_ENABLED_VALIDATOR);
}
/**
@@ -15382,4 +15393,4 @@ public final class Settings {
}
return packages[0];
}
-}
+} \ No newline at end of file
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index 87e369f20d58..66c3e1966134 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -228,7 +228,7 @@ public abstract class AugmentedAutofillService extends Service {
} else {
// TODO(b/123099468): figure out if it's ok to reuse the proxy; add logging
if (sDebug) Log.d(TAG, "Reusing proxy for session " + sessionId);
- proxy.update(focusedId, focusedValue, callback);
+ proxy.update(focusedId, focusedValue, callback, cancellationSignal);
}
try {
@@ -252,6 +252,15 @@ public abstract class AugmentedAutofillService extends Service {
Log.w(TAG, "No proxy for session " + sessionId);
return;
}
+ if (proxy.mCallback != null) {
+ try {
+ if (!proxy.mCallback.isCompleted()) {
+ proxy.mCallback.cancel();
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "failed to check current pending request status", e);
+ }
+ }
proxy.destroy();
}
mAutofillProxies.clear();
@@ -442,7 +451,7 @@ public abstract class AugmentedAutofillService extends Service {
}
private void update(@NonNull AutofillId focusedId, @NonNull AutofillValue focusedValue,
- @NonNull IFillCallback callback) {
+ @NonNull IFillCallback callback, @NonNull CancellationSignal cancellationSignal) {
synchronized (mLock) {
mFocusedId = focusedId;
mFocusedValue = focusedValue;
@@ -457,6 +466,7 @@ public abstract class AugmentedAutofillService extends Service {
Log.d(TAG, "mCallback is updated.");
}
mCallback = callback;
+ mCancellationSignal = cancellationSignal;
}
}
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 08d9733ac815..397a6cdf3bee 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -162,7 +162,7 @@ public abstract class ContentCaptureService extends Service {
@Override
public void onDataRemovalRequest(DataRemovalRequest request) {
mHandler.sendMessage(
- obtainMessage(ContentCaptureService::handleOnUserDataRemovalRequest,
+ obtainMessage(ContentCaptureService::handleOnDataRemovalRequest,
ContentCaptureService.this, request));
}
@@ -503,7 +503,7 @@ public abstract class ContentCaptureService extends Service {
onDestroyContentCaptureSession(new ContentCaptureSessionId(sessionId));
}
- private void handleOnUserDataRemovalRequest(@NonNull DataRemovalRequest request) {
+ private void handleOnDataRemovalRequest(@NonNull DataRemovalRequest request) {
onDataRemovalRequest(request);
}
diff --git a/core/java/android/service/quicksettings/Tile.java b/core/java/android/service/quicksettings/Tile.java
index 419104033bcd..79c21521fe2d 100644
--- a/core/java/android/service/quicksettings/Tile.java
+++ b/core/java/android/service/quicksettings/Tile.java
@@ -65,8 +65,8 @@ public final class Tile implements Parcelable {
private CharSequence mLabel;
private CharSequence mSubtitle;
private CharSequence mContentDescription;
- // Default to active until clients of the new API can update.
- private int mState = STATE_ACTIVE;
+ // Default to inactive until clients of the new API can update.
+ private int mState = STATE_INACTIVE;
private IQSService mService;
diff --git a/core/java/android/service/wallpaper/Android.bp b/core/java/android/service/wallpaper/Android.bp
new file mode 100644
index 000000000000..aa6123f5a983
--- /dev/null
+++ b/core/java/android/service/wallpaper/Android.bp
@@ -0,0 +1,12 @@
+android_library {
+
+ name: "WallpaperSharedLib",
+ srcs: [
+ "*.java",
+ "I*.aidl",
+ ],
+
+ // Enforce that the library is built against java 8 so that there are
+ // no compatibility issues with launcher
+ java_version: "1.8",
+}
diff --git a/core/java/android/service/wallpaper/AndroidManifest.xml b/core/java/android/service/wallpaper/AndroidManifest.xml
new file mode 100644
index 000000000000..f1bdb76409fb
--- /dev/null
+++ b/core/java/android/service/wallpaper/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.service.wallpaper">
+
+ <uses-sdk android:minSdkVersion="29" />
+</manifest>
diff --git a/core/java/android/text/Emoji.java b/core/java/android/text/Emoji.java
index 876c64eebf84..04fa1106bab2 100644
--- a/core/java/android/text/Emoji.java
+++ b/core/java/android/text/Emoji.java
@@ -73,22 +73,20 @@ public class Emoji {
* Returns true if the character is a new emoji still not supported in our version of ICU.
*/
public static boolean isNewEmoji(int c) {
- // Emoji characters new in Unicode emoji 11
- // From https://www.unicode.org/Public/emoji/11.0/emoji-data.txt
- // TODO: Remove once emoji-data.text 11 is in ICU or update to 11.
- if (c < 0x1F6F9 || c > 0x1F9FF) {
+ // Emoji characters new in Unicode emoji 12
+ // From https://www.unicode.org/Public/emoji/12.0/emoji-data.txt
+ // TODO: Remove once emoji-data.text 12 is in ICU or update to 12.
+ if (c < 0x1F6D5 || c > 0x1FA95) {
// Optimization for characters outside the new emoji range.
return false;
}
- return c == 0x265F || c == 0x267E || c == 0x1F6F9 || c == 0x1F97A
- || (0x1F94D <= c && c <= 0x1F94F)
- || (0x1F96C <= c && c <= 0x1F970)
- || (0x1F973 <= c && c <= 0x1F976)
- || (0x1F97C <= c && c <= 0x1F97F)
- || (0x1F998 <= c && c <= 0x1F9A2)
- || (0x1F9B0 <= c && c <= 0x1F9B9)
- || (0x1F9C1 <= c && c <= 0x1F9C2)
- || (0x1F9E7 <= c && c <= 0x1F9FF);
+ return c == 0x1F6D5 || c == 0x1F6FA || c == 0x1F93F || c == 0x1F971 || c == 0x1F97B
+ || (0x1F7E0 <= c && c <= 0x1F7EB) || (0x1F90D <= c && c <= 0x1F90F)
+ || (0x1F9A5 <= c && c <= 0x1F9AA) || (0x1F9AE <= c && c <= 0x1F9AF)
+ || (0x1F9BA <= c && c <= 0x1F9BF) || (0x1F9C3 <= c && c <= 0x1F9CA)
+ || (0x1F9CD <= c && c <= 0x1F9CF) || (0x1FA70 <= c && c <= 0x1FA73)
+ || (0x1FA78 <= c && c <= 0x1FA7A) || (0x1FA80 <= c && c <= 0x1FA82)
+ || (0x1FA90 <= c && c <= 0x1FA95);
}
/**
diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java
index 80b16075cdf6..7d287e38ba86 100644
--- a/core/java/android/util/MemoryIntArray.java
+++ b/core/java/android/util/MemoryIntArray.java
@@ -175,12 +175,10 @@ public final class MemoryIntArray implements Parcelable, Closeable {
@Override
public void writeToParcel(Parcel parcel, int flags) {
- ParcelFileDescriptor pfd = ParcelFileDescriptor.adoptFd(mFd);
- try {
- // Don't let writing to a parcel to close our fd - plz
- parcel.writeParcelable(pfd, flags & ~Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
- } finally {
- pfd.detachFd();
+ try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromFd(mFd)) {
+ parcel.writeParcelable(pfd, flags);
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
}
}
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index c2f96013142b..93f52a04d626 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -213,7 +213,7 @@ public class RenderNodeAnimator extends Animator {
// it with the final value here.
if (mRenderProperty == RenderNodeAnimator.ALPHA) {
mViewTarget.ensureTransformationInfo();
- mViewTarget.mTransformationInfo.mAlpha = mFinalValue;
+ mViewTarget.setAlphaInternal(mFinalValue);
}
moveToRunningState();
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 7fdda2a22c17..254d04e8715d 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -24,8 +24,10 @@ import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.CompatibilityInfo.Translator;
import android.content.res.Configuration;
+import android.graphics.BlendMode;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.Rect;
@@ -127,6 +129,8 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
final Rect mTmpRect = new Rect();
final Configuration mConfiguration = new Configuration();
+ Paint mRoundedViewportPaint;
+
int mSubLayer = APPLICATION_MEDIA_SUBLAYER;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -180,6 +184,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
int mWindowSpaceTop = -1;
int mSurfaceWidth = -1;
int mSurfaceHeight = -1;
+ float mCornerRadius;
@UnsupportedAppUsage
int mFormat = -1;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -395,7 +400,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
// draw() is not called when SKIP_DRAW is set
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
// punch a whole in the view-hierarchy below us
- canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+ clearSurfaceViewPort(canvas);
}
}
super.draw(canvas);
@@ -407,12 +412,39 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
// draw() is not called when SKIP_DRAW is set
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
// punch a whole in the view-hierarchy below us
- canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+ clearSurfaceViewPort(canvas);
}
}
super.dispatchDraw(canvas);
}
+ private void clearSurfaceViewPort(Canvas canvas) {
+ if (mCornerRadius > 0f) {
+ canvas.getClipBounds(mTmpRect);
+ canvas.drawRoundRect(mTmpRect.left, mTmpRect.top, mTmpRect.right, mTmpRect.bottom,
+ mCornerRadius, mCornerRadius, mRoundedViewportPaint);
+ } else {
+ canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+ }
+ }
+
+ /**
+ * Sets the corner radius for the SurfaceView. This will round both the corners of the
+ * underlying surface, as well as the corners of the hole created to expose the surface.
+ *
+ * @param cornerRadius the new radius of the corners in pixels
+ * @hide
+ */
+ public void setCornerRadius(float cornerRadius) {
+ mCornerRadius = cornerRadius;
+ if (mCornerRadius > 0f && mRoundedViewportPaint == null) {
+ mRoundedViewportPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mRoundedViewportPaint.setBlendMode(BlendMode.CLEAR);
+ mRoundedViewportPaint.setColor(0);
+ }
+ invalidate();
+ }
+
/**
* Control whether the surface view's surface is placed on top of another
* regular surface view in the window (but still behind the window itself).
@@ -634,6 +666,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
// size.
mSurfaceControl.setWindowCrop(mSurfaceWidth, mSurfaceHeight);
}
+ mSurfaceControl.setCornerRadius(mCornerRadius);
if (sizeChanged && !creating) {
mSurfaceControl.setBufferSize(mSurfaceWidth, mSurfaceHeight);
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 85580aad7b4e..bf6191ec61eb 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4123,7 +4123,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* completely transparent and 1 means completely opaque.
*/
@ViewDebug.ExportedProperty
- float mAlpha = 1f;
+ private float mAlpha = 1f;
/**
* The opacity of the view as manipulated by the Fade transition. This is a
@@ -8852,6 +8852,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* @hide
*/
+ @TestApi
public boolean isAutofilled() {
return (mPrivateFlags3 & PFLAG3_IS_AUTOFILLED) != 0;
}
@@ -9076,18 +9077,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* <pre>
* ContentCaptureSession mainSession = rootView.getContentCaptureSession();
* mainSession.setContentCaptureContext(ContentCaptureContext.forLocusId(Uri.parse(myUrl));
- * <pre>
+ * </pre>
*
* <p>Then if the page had an {@code IFRAME}, you would create a new session for it:
*
- * <p>For example, if your activity is associated with a web domain, you could create a session
- * {@code onCreate()} and associate it with the root view of the activity:
- *
* <pre>
* ContentCaptureSession iframeSession = mainSession.createContentCaptureSession(
* ContentCaptureContext.forLocusId(Uri.parse(iframeUrl)));
* iframeView.setContentCaptureSession(iframeSession);
- * <pre>
+ * </pre>
*
* @param contentCaptureSession a session created by
* {@link ContentCaptureSession#createContentCaptureSession(
@@ -16190,7 +16188,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return false;
}
- private void setAlphaInternal(float alpha) {
+ void setAlphaInternal(float alpha) {
float oldAlpha = mTransformationInfo.mAlpha;
mTransformationInfo.mAlpha = alpha;
// Report visibility changes, which can affect children, to accessibility
@@ -21511,23 +21509,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
saveCount = canvas.getSaveCount();
+ int topSaveCount = -1;
+ int bottomSaveCount = -1;
+ int leftSaveCount = -1;
+ int rightSaveCount = -1;
int solidColor = getSolidColor();
if (solidColor == 0) {
if (drawTop) {
- canvas.saveUnclippedLayer(left, top, right, top + length);
+ topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
}
if (drawBottom) {
- canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
+ bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
}
if (drawLeft) {
- canvas.saveUnclippedLayer(left, top, left + length, bottom);
+ leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
}
if (drawRight) {
- canvas.saveUnclippedLayer(right - length, top, right, bottom);
+ rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom);
}
} else {
scrollabilityCache.setFadeColor(solidColor);
@@ -21544,12 +21546,32 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
final Matrix matrix = scrollabilityCache.matrix;
final Shader fade = scrollabilityCache.shader;
- if (drawTop) {
- matrix.setScale(1, fadeHeight * topFadeStrength);
+ // must be restored in the reverse order that they were saved
+ if (drawRight) {
+ matrix.setScale(1, fadeHeight * rightFadeStrength);
+ matrix.postRotate(90);
+ matrix.postTranslate(right, top);
+ fade.setLocalMatrix(matrix);
+ p.setShader(fade);
+ if (solidColor == 0) {
+ canvas.restoreUnclippedLayer(rightSaveCount, p);
+
+ } else {
+ canvas.drawRect(right - length, top, right, bottom, p);
+ }
+ }
+
+ if (drawLeft) {
+ matrix.setScale(1, fadeHeight * leftFadeStrength);
+ matrix.postRotate(-90);
matrix.postTranslate(left, top);
fade.setLocalMatrix(matrix);
p.setShader(fade);
- canvas.drawRect(left, top, right, top + length, p);
+ if (solidColor == 0) {
+ canvas.restoreUnclippedLayer(leftSaveCount, p);
+ } else {
+ canvas.drawRect(left, top, left + length, bottom, p);
+ }
}
if (drawBottom) {
@@ -21558,25 +21580,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
matrix.postTranslate(left, bottom);
fade.setLocalMatrix(matrix);
p.setShader(fade);
- canvas.drawRect(left, bottom - length, right, bottom, p);
+ if (solidColor == 0) {
+ canvas.restoreUnclippedLayer(bottomSaveCount, p);
+ } else {
+ canvas.drawRect(left, bottom - length, right, bottom, p);
+ }
}
- if (drawLeft) {
- matrix.setScale(1, fadeHeight * leftFadeStrength);
- matrix.postRotate(-90);
+ if (drawTop) {
+ matrix.setScale(1, fadeHeight * topFadeStrength);
matrix.postTranslate(left, top);
fade.setLocalMatrix(matrix);
p.setShader(fade);
- canvas.drawRect(left, top, left + length, bottom, p);
- }
-
- if (drawRight) {
- matrix.setScale(1, fadeHeight * rightFadeStrength);
- matrix.postRotate(90);
- matrix.postTranslate(right, top);
- fade.setLocalMatrix(matrix);
- p.setShader(fade);
- canvas.drawRect(right - length, top, right, bottom, p);
+ if (solidColor == 0) {
+ canvas.restoreUnclippedLayer(topSaveCount, p);
+ } else {
+ canvas.drawRect(left, top, right, top + length, p);
+ }
}
canvas.restoreToCount(saveCount);
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index afee1e5cf7f4..957673dba133 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -972,7 +972,6 @@ public class ViewPropertyAnimator {
* @param value The value to set the property to
*/
private void setValue(int propertyConstant, float value) {
- final View.TransformationInfo info = mView.mTransformationInfo;
final RenderNode renderNode = mView.mRenderNode;
switch (propertyConstant) {
case TRANSLATION_X:
@@ -1009,7 +1008,7 @@ public class ViewPropertyAnimator {
renderNode.setTranslationZ(value - renderNode.getElevation());
break;
case ALPHA:
- info.mAlpha = value;
+ mView.setAlphaInternal(value);
renderNode.setAlpha(value);
break;
}
@@ -1047,7 +1046,7 @@ public class ViewPropertyAnimator {
case Z:
return node.getElevation() + node.getTranslationZ();
case ALPHA:
- return mView.mTransformationInfo.mAlpha;
+ return mView.getAlpha();
}
return 0;
}
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index c36b8940b158..1f7ae0e7e245 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1204,10 +1204,6 @@ public final class AutofillManager {
AutofillValue value = null;
synchronized (mLock) {
- if (mForAugmentedAutofillOnly) {
- if (sVerbose) Log.v(TAG, "notifyValueChanged(): ignoring on augmented only mode");
- return;
- }
// If the session is gone some fields might still be highlighted, hence we have to
// remove the isAutofilled property even if no sessions are active.
if (mLastAutofilledData == null) {
@@ -1229,6 +1225,13 @@ public final class AutofillManager {
}
}
+ if (mForAugmentedAutofillOnly) {
+ if (sVerbose) {
+ Log.v(TAG, "notifyValueChanged(): not notifying system server on "
+ + "augmented-only mode");
+ }
+ return;
+ }
if (!mEnabled || !isActiveLocked()) {
if (sVerbose) {
Log.v(TAG, "notifyValueChanged(" + view.getAutofillId()
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 210dea1894bf..31cb4e2f5ad2 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -41,7 +41,7 @@ import java.util.ArrayList;
import java.util.Random;
/**
- * Session used to notify the Android system about events associated with views.
+ * Session used when notifying the Android system about events associated with views.
*/
public abstract class ContentCaptureSession implements AutoCloseable {
diff --git a/core/java/android/view/contentcapture/DataRemovalRequest.java b/core/java/android/view/contentcapture/DataRemovalRequest.java
index 3792846bea71..68d4695aa840 100644
--- a/core/java/android/view/contentcapture/DataRemovalRequest.java
+++ b/core/java/android/view/contentcapture/DataRemovalRequest.java
@@ -32,6 +32,9 @@ import java.util.List;
/**
* Class used by apps to remove content capture data associated with {@link LocusId LocusIds}.
+ *
+ * <p>An app which has tagged data with a LocusId can therefore delete them later. This is intended
+ * to let apps propagate deletions of user data into the operating system.
*/
public final class DataRemovalRequest implements Parcelable {
diff --git a/core/java/android/view/textclassifier/SelectionSessionLogger.java b/core/java/android/view/textclassifier/SelectionSessionLogger.java
index 48a568abb169..20cc94433872 100644
--- a/core/java/android/view/textclassifier/SelectionSessionLogger.java
+++ b/core/java/android/view/textclassifier/SelectionSessionLogger.java
@@ -80,12 +80,16 @@ public final class SelectionSessionLogger {
.addTaggedData(INDEX, event.getEventIndex())
.addTaggedData(WIDGET_TYPE, event.getWidgetType())
.addTaggedData(WIDGET_VERSION, event.getWidgetVersion())
- .addTaggedData(MODEL_NAME, SignatureParser.getModelName(event.getResultId()))
.addTaggedData(ENTITY_TYPE, event.getEntityType())
- .addTaggedData(SMART_START, event.getSmartStart())
- .addTaggedData(SMART_END, event.getSmartEnd())
.addTaggedData(EVENT_START, event.getStart())
.addTaggedData(EVENT_END, event.getEnd());
+ if (isPlatformLocalTextClassifierSmartSelection(event.getResultId())) {
+ // Ensure result id and smart indices are only set for events with smart selection from
+ // the platform's textclassifier.
+ log.addTaggedData(MODEL_NAME, SignatureParser.getModelName(event.getResultId()))
+ .addTaggedData(SMART_START, event.getSmartStart())
+ .addTaggedData(SMART_END, event.getSmartEnd());
+ }
if (event.getSessionId() != null) {
log.addTaggedData(SESSION_ID, event.getSessionId().flattenToString());
}
@@ -193,6 +197,11 @@ public final class SelectionSessionLogger {
}
}
+ static boolean isPlatformLocalTextClassifierSmartSelection(String signature) {
+ return SelectionSessionLogger.CLASSIFIER_ID.equals(
+ SelectionSessionLogger.SignatureParser.getClassifierId(signature));
+ }
+
private static void debugLog(LogMaker log) {
if (!Log.ENABLE_FULL_LOGGING) {
return;
diff --git a/core/java/android/view/textclassifier/TextClassificationSession.java b/core/java/android/view/textclassifier/TextClassificationSession.java
index ba1287fc6b0f..15f54ef2a623 100644
--- a/core/java/android/view/textclassifier/TextClassificationSession.java
+++ b/core/java/android/view/textclassifier/TextClassificationSession.java
@@ -158,11 +158,11 @@ final class TextClassificationSession implements TextClassifier {
mStartEvent = event;
break;
case SelectionEvent.EVENT_SMART_SELECTION_SINGLE: // fall through
- case SelectionEvent.EVENT_SMART_SELECTION_MULTI:
+ case SelectionEvent.EVENT_SMART_SELECTION_MULTI: // fall through
+ case SelectionEvent.EVENT_AUTO_SELECTION:
mSmartEvent = event;
break;
- case SelectionEvent.EVENT_SELECTION_MODIFIED: // fall through
- case SelectionEvent.EVENT_AUTO_SELECTION:
+ case SelectionEvent.EVENT_SELECTION_MODIFIED:
if (mPrevEvent != null
&& mPrevEvent.getAbsoluteStart() == event.getAbsoluteStart()
&& mPrevEvent.getAbsoluteEnd() == event.getAbsoluteEnd()) {
@@ -215,7 +215,8 @@ final class TextClassificationSession implements TextClassifier {
case SelectionEvent.EVENT_SMART_SELECTION_SINGLE: // fall through
case SelectionEvent.EVENT_SMART_SELECTION_MULTI: // fall through
case SelectionEvent.EVENT_AUTO_SELECTION:
- if (isPlatformLocalTextClassifierSmartSelection(event.getResultId())) {
+ if (SelectionSessionLogger.isPlatformLocalTextClassifierSmartSelection(
+ event.getResultId())) {
if (event.getAbsoluteEnd() - event.getAbsoluteStart() > 1) {
event.setEventType(SelectionEvent.EVENT_SMART_SELECTION_MULTI);
} else {
@@ -229,10 +230,5 @@ final class TextClassificationSession implements TextClassifier {
return;
}
}
-
- private static boolean isPlatformLocalTextClassifierSmartSelection(String signature) {
- return SelectionSessionLogger.CLASSIFIER_ID.equals(
- SelectionSessionLogger.SignatureParser.getClassifierId(signature));
- }
}
}
diff --git a/core/java/android/widget/TextClock.java b/core/java/android/widget/TextClock.java
index 616c4b51eca0..b7dd88bcedc6 100644
--- a/core/java/android/widget/TextClock.java
+++ b/core/java/android/widget/TextClock.java
@@ -175,6 +175,9 @@ public class TextClock extends TextView {
if (mTimeZone == null && Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
final String timeZone = intent.getStringExtra("time-zone");
createTime(timeZone);
+ } else if (!mShouldRunTicker && (Intent.ACTION_TIME_TICK.equals(intent.getAction())
+ || Intent.ACTION_TIME_CHANGED.equals(intent.getAction()))) {
+ return;
}
onTimeChanged();
}
@@ -642,12 +645,9 @@ public class TextClock extends TextView {
*/
@UnsupportedAppUsage
private void onTimeChanged() {
- // mShouldRunTicker always equals the last value passed into onVisibilityAggregated
- if (mShouldRunTicker) {
- mTime.setTimeInMillis(System.currentTimeMillis());
- setText(DateFormat.format(mFormat, mTime));
- setContentDescription(DateFormat.format(mDescFormat, mTime));
- }
+ mTime.setTimeInMillis(System.currentTimeMillis());
+ setText(DateFormat.format(mFormat, mTime));
+ setContentDescription(DateFormat.format(mDescFormat, mTime));
}
/** @hide */
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 17c56c3f216a..a9e183ad5bf2 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -11244,13 +11244,23 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Nullable
final TextServicesManager getTextServicesManagerForUser() {
+ return getServiceManagerForUser("android", TextServicesManager.class);
+ }
+
+ @Nullable
+ final ClipboardManager getClipboardManagerForUser() {
+ return getServiceManagerForUser(getContext().getPackageName(), ClipboardManager.class);
+ }
+
+ @Nullable
+ final <T> T getServiceManagerForUser(String packageName, Class<T> managerClazz) {
if (mTextOperationUser == null) {
- return getContext().getSystemService(TextServicesManager.class);
+ return getContext().getSystemService(managerClazz);
}
try {
- return getContext().createPackageContextAsUser(
- "android", 0 /* flags */, mTextOperationUser)
- .getSystemService(TextServicesManager.class);
+ Context context = getContext().createPackageContextAsUser(
+ packageName, 0 /* flags */, mTextOperationUser);
+ return context.getSystemService(managerClazz);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
@@ -12540,8 +12550,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
&& mEditor != null && mEditor.mKeyListener != null
&& getSelectionStart() >= 0
&& getSelectionEnd() >= 0
- && ((ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE))
- .hasPrimaryClip());
+ && getClipboardManagerForUser().hasPrimaryClip());
}
boolean canPasteAsPlainText() {
@@ -12549,9 +12558,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return false;
}
- final ClipData clipData =
- ((ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE))
- .getPrimaryClip();
+ final ClipData clipData = getClipboardManagerForUser().getPrimaryClip();
final ClipDescription description = clipData.getDescription();
final boolean isPlainType = description.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN);
final CharSequence text = clipData.getItemAt(0).getText();
@@ -12594,8 +12601,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* Paste clipboard content between min and max positions.
*/
private void paste(int min, int max, boolean withFormatting) {
- ClipboardManager clipboard =
- (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
+ ClipboardManager clipboard = getClipboardManagerForUser();
ClipData clip = clipboard.getPrimaryClip();
if (clip != null) {
boolean didFirst = false;
@@ -12638,8 +12644,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@CheckResult
private boolean setPrimaryClip(ClipData clip) {
- ClipboardManager clipboard =
- (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
+ ClipboardManager clipboard = getClipboardManagerForUser();
try {
clipboard.setPrimaryClip(clip);
} catch (Throwable t) {
diff --git a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
index 3fddfc8a4602..04ad7e9ee8a7 100644
--- a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
+++ b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
@@ -99,9 +99,13 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator
}
List<AppTarget> appTargets = new ArrayList<>();
for (ResolvedComponentInfo target : targets) {
- appTargets.add(new AppTarget.Builder(new AppTargetId(target.name.flattenToString()))
- .setTarget(target.name.getPackageName(), mUser)
- .setClassName(target.name.getClassName()).build());
+ appTargets.add(
+ new AppTarget.Builder(
+ new AppTargetId(target.name.flattenToString()),
+ target.name.getPackageName(),
+ mUser)
+ .setClassName(target.name.getClassName())
+ .build());
}
mAppPredictor.sortTargets(appTargets, Executors.newSingleThreadExecutor(),
sortedAppTargets -> {
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 5924fb15d8af..a88c51a28229 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -32,7 +32,6 @@ import android.app.prediction.AppPredictionManager;
import android.app.prediction.AppPredictor;
import android.app.prediction.AppTarget;
import android.app.prediction.AppTargetEvent;
-import android.app.prediction.AppTargetId;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.ComponentName;
@@ -125,7 +124,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* The Chooser Activity handles intent resolution specifically for sharing intents -
@@ -162,6 +163,7 @@ public class ChooserActivity extends ResolverActivity {
public static final String APP_PREDICTION_INTENT_FILTER_KEY = "intent_filter";
private AppPredictor mAppPredictor;
private AppPredictor.Callback mAppPredictorCallback;
+ private Map<ChooserTarget, AppTarget> mDirectShareAppTargetCache;
/**
* If set to true, use ShortcutManager to retrieve the matching direct share targets, instead of
@@ -235,7 +237,6 @@ public class ChooserActivity extends ResolverActivity {
private boolean mListViewDataChanged = false;
-
@Retention(SOURCE)
@IntDef({CONTENT_PREVIEW_FILE, CONTENT_PREVIEW_IMAGE, CONTENT_PREVIEW_TEXT})
private @interface ContentPreviewType {
@@ -454,6 +455,7 @@ public class ChooserActivity extends ResolverActivity {
AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled();
if (appPredictor != null) {
+ mDirectShareAppTargetCache = new HashMap<>();
mAppPredictorCallback = resultList -> {
if (isFinishing() || isDestroyed()) {
return;
@@ -480,8 +482,7 @@ public class ChooserActivity extends ResolverActivity {
new ComponentName(
appTarget.getPackageName(), appTarget.getClassName())));
}
- sendShareShortcutInfoList(shareShortcutInfos, driList);
- sendShortcutManagerShareTargetResultCompleted();
+ sendShareShortcutInfoList(shareShortcutInfos, driList, resultList);
};
appPredictor
.registerPredictionUpdates(this.getMainExecutor(), mAppPredictorCallback);
@@ -1318,13 +1319,14 @@ public class ChooserActivity extends ResolverActivity {
AsyncTask.execute(() -> {
ShortcutManager sm = (ShortcutManager) getSystemService(Context.SHORTCUT_SERVICE);
List<ShortcutManager.ShareShortcutInfo> resultList = sm.getShareTargets(filter);
- sendShareShortcutInfoList(resultList, driList);
+ sendShareShortcutInfoList(resultList, driList, null);
});
}
private void sendShareShortcutInfoList(
List<ShortcutManager.ShareShortcutInfo> resultList,
- List<DisplayResolveInfo> driList) {
+ List<DisplayResolveInfo> driList,
+ @Nullable List<AppTarget> appTargets) {
// Match ShareShortcutInfos with DisplayResolveInfos to be able to use the old code path
// for direct share targets. After ShareSheet is refactored we should use the
// ShareShortcutInfos directly.
@@ -1334,7 +1336,13 @@ public class ChooserActivity extends ResolverActivity {
for (int j = 0; j < resultList.size(); j++) {
if (driList.get(i).getResolvedComponentName().equals(
resultList.get(j).getTargetComponent())) {
- chooserTargets.add(convertToChooserTarget(resultList.get(j)));
+ ShortcutManager.ShareShortcutInfo shareShortcutInfo = resultList.get(j);
+ ChooserTarget chooserTarget = convertToChooserTarget(shareShortcutInfo);
+ chooserTargets.add(chooserTarget);
+ if (mDirectShareAppTargetCache != null && appTargets != null) {
+ // Note that appTargets.size() == resultList.size() is always true.
+ mDirectShareAppTargetCache.put(chooserTarget, appTargets.get(j));
+ }
}
}
if (chooserTargets.isEmpty()) {
@@ -1442,33 +1450,25 @@ public class ChooserActivity extends ResolverActivity {
}
private void sendClickToAppPredictor(TargetInfo targetInfo) {
- AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled();
- if (appPredictor == null) {
+ AppPredictor directShareAppPredictor = getAppPredictorForDirectShareIfEnabled();
+ if (directShareAppPredictor == null) {
return;
}
if (!(targetInfo instanceof ChooserTargetInfo)) {
return;
}
ChooserTarget chooserTarget = ((ChooserTargetInfo) targetInfo).getChooserTarget();
- ComponentName componentName = chooserTarget.getComponentName();
- Bundle extras = chooserTarget.getIntentExtras();
- if (extras == null) {
- return;
+ AppTarget appTarget = null;
+ if (mDirectShareAppTargetCache != null) {
+ appTarget = mDirectShareAppTargetCache.get(chooserTarget);
}
- String shortcutId = extras.getString(Intent.EXTRA_SHORTCUT_ID);
- if (shortcutId == null) {
- return;
+ // This is a direct share click that was provided by the APS
+ if (appTarget != null) {
+ directShareAppPredictor.notifyAppTargetEvent(
+ new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH)
+ .setLaunchLocation(LAUNCH_LOCATON_DIRECT_SHARE)
+ .build());
}
- appPredictor.notifyAppTargetEvent(
- new AppTargetEvent.Builder(
- // TODO(b/124404997) Send full shortcut info, not just Id with AppTargetId.
- new AppTarget.Builder(new AppTargetId(shortcutId),
- componentName.getPackageName(), getUser())
- .setClassName(componentName.getClassName())
- .build(),
- AppTargetEvent.ACTION_LAUNCH)
- .setLaunchLocation(LAUNCH_LOCATON_DIRECT_SHARE)
- .build());
}
@Nullable
@@ -2035,7 +2035,8 @@ public class ChooserActivity extends ResolverActivity {
return;
}
- if (mChooserRowAdapter.calculateChooserTargetWidth(right - left)
+ int availableWidth = right - left - v.getPaddingLeft() - v.getPaddingRight();
+ if (mChooserRowAdapter.calculateChooserTargetWidth(availableWidth)
|| mAdapterView.getAdapter() == null) {
mAdapterView.setAdapter(mChooserRowAdapter);
@@ -2044,7 +2045,9 @@ public class ChooserActivity extends ResolverActivity {
return;
}
- int offset = 0;
+ final int bottomInset = mSystemWindowInsets != null
+ ? mSystemWindowInsets.bottom : 0;
+ int offset = bottomInset;
int rowsToShow = mChooserRowAdapter.getContentPreviewRowCount()
+ mChooserRowAdapter.getProfileRowCount()
+ mChooserRowAdapter.getServiceTargetRowCount()
@@ -2059,7 +2062,7 @@ public class ChooserActivity extends ResolverActivity {
// still zero? then use a default height and leave, which
// can happen when there are no targets to show
if (rowsToShow == 0) {
- offset = getResources().getDimensionPixelSize(
+ offset += getResources().getDimensionPixelSize(
R.dimen.chooser_max_collapsed_height);
mResolverDrawerLayout.setCollapsibleHeightReserved(offset);
return;
@@ -2084,8 +2087,9 @@ public class ChooserActivity extends ResolverActivity {
// make sure to leave room for direct share 4->8 expansion
int requiredExpansionHeight =
(int) (directShareHeight / DIRECT_SHARE_EXPANSION_RATE);
+ int topInset = mSystemWindowInsets != null ? mSystemWindowInsets.top : 0;
int minHeight = bottom - top - mResolverDrawerLayout.getAlwaysShowHeight()
- - requiredExpansionHeight;
+ - requiredExpansionHeight - topInset - bottomInset;
offset = Math.min(offset, minHeight);
}
@@ -2655,7 +2659,7 @@ public class ChooserActivity extends ResolverActivity {
@Override
public boolean isEnabled(int position) {
int viewType = getItemViewType(position);
- if (viewType == VIEW_TYPE_CONTENT_PREVIEW) {
+ if (viewType == VIEW_TYPE_CONTENT_PREVIEW || viewType == VIEW_TYPE_AZ_LABEL) {
return false;
}
return true;
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 3ea746d5f417..a5daa0ae81e6 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -46,6 +46,7 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Insets;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
@@ -67,12 +68,15 @@ import android.util.Slog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.view.WindowInsets;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
+import android.widget.Space;
import android.widget.TextView;
import android.widget.Toast;
@@ -136,6 +140,9 @@ public class ResolverActivity extends Activity {
private ColorMatrixColorFilter mSuspendedMatrixColorFilter;
+ protected Insets mSystemWindowInsets = null;
+ private Space mFooterSpacer = null;
+
/** See {@link #setRetainInOnStop}. */
private boolean mRetainInOnStop;
@@ -329,6 +336,11 @@ public class ResolverActivity extends Activity {
if (isVoiceInteraction()) {
rdl.setCollapsed(false);
}
+
+ rdl.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+ rdl.setOnApplyWindowInsetsListener(this::onApplyWindowInsets);
+
mResolverDrawerLayout = rdl;
}
@@ -364,10 +376,38 @@ public class ResolverActivity extends Activity {
finish();
}
+ protected WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
+ mSystemWindowInsets = insets.getSystemWindowInsets();
+
+ mResolverDrawerLayout.setPadding(mSystemWindowInsets.left, mSystemWindowInsets.top,
+ mSystemWindowInsets.right, 0);
+
+ View emptyView = findViewById(R.id.empty);
+ emptyView.setPadding(0, 0, 0, mSystemWindowInsets.bottom
+ + getResources().getDimensionPixelSize(
+ R.dimen.chooser_edge_margin_normal) * 2);
+
+ if (mFooterSpacer == null) {
+ mFooterSpacer = new Space(getApplicationContext());
+ } else {
+ ((ListView) mAdapterView).removeFooterView(mFooterSpacer);
+ }
+ mFooterSpacer.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT,
+ mSystemWindowInsets.bottom));
+ ((ListView) mAdapterView).addFooterView(mFooterSpacer);
+
+ return insets.consumeSystemWindowInsets();
+ }
+
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mAdapter.handlePackagesChanged();
+
+ if (mSystemWindowInsets != null) {
+ mResolverDrawerLayout.setPadding(mSystemWindowInsets.left, mSystemWindowInsets.top,
+ mSystemWindowInsets.right, 0);
+ }
}
private void initSuspendedColorMatrix() {
@@ -1277,6 +1317,10 @@ public class ResolverActivity extends Activity {
final ViewGroup buttonLayout = findViewById(R.id.button_bar);
if (buttonLayout != null) {
buttonLayout.setVisibility(View.VISIBLE);
+ int inset = mSystemWindowInsets != null ? mSystemWindowInsets.bottom : 0;
+ buttonLayout.setPadding(buttonLayout.getPaddingLeft(), buttonLayout.getPaddingTop(),
+ buttonLayout.getPaddingRight(), buttonLayout.getPaddingBottom() + inset);
+
mOnceButton = (Button) buttonLayout.findViewById(R.id.button_once);
mSettingsButton = (Button) buttonLayout.findViewById(R.id.button_app_settings);
mAlwaysButton = (Button) buttonLayout.findViewById(R.id.button_always);
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 7e501d27d30f..c715577cb7d2 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -167,4 +167,9 @@ oneway interface IStatusBar
* Notifies System UI that the display is ready to show system decorations.
*/
void onDisplayReady(int displayId);
+
+ /**
+ * Notifies System UI whether the recents animation is running or not.
+ */
+ void onRecentsAnimationStateChanged(boolean running);
}
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index 3adb36f5e54b..c73de8fad5b2 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -854,12 +854,11 @@ public class ResolverDrawerLayout extends ViewGroup {
final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
final int heightSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);
- final int widthPadding = getPaddingLeft() + getPaddingRight();
// Currently we allot more height than is really needed so that the entirety of the
// sheet may be pulled up.
// TODO: Restrict the height here to be the right value.
- int heightUsed = getPaddingTop() + getPaddingBottom();
+ int heightUsed = 0;
// Measure always-show children first.
final int childCount = getChildCount();
@@ -869,11 +868,11 @@ public class ResolverDrawerLayout extends ViewGroup {
if (lp.alwaysShow && child.getVisibility() != GONE) {
if (lp.maxHeight != -1) {
final int remainingHeight = heightSize - heightUsed;
- measureChildWithMargins(child, widthSpec, widthPadding,
+ measureChildWithMargins(child, widthSpec, 0,
MeasureSpec.makeMeasureSpec(lp.maxHeight, MeasureSpec.AT_MOST),
lp.maxHeight > remainingHeight ? lp.maxHeight - remainingHeight : 0);
} else {
- measureChildWithMargins(child, widthSpec, widthPadding, heightSpec, heightUsed);
+ measureChildWithMargins(child, widthSpec, 0, heightSpec, heightUsed);
}
heightUsed += child.getMeasuredHeight();
}
@@ -889,11 +888,11 @@ public class ResolverDrawerLayout extends ViewGroup {
if (!lp.alwaysShow && child.getVisibility() != GONE) {
if (lp.maxHeight != -1) {
final int remainingHeight = heightSize - heightUsed;
- measureChildWithMargins(child, widthSpec, widthPadding,
+ measureChildWithMargins(child, widthSpec, 0,
MeasureSpec.makeMeasureSpec(lp.maxHeight, MeasureSpec.AT_MOST),
lp.maxHeight > remainingHeight ? lp.maxHeight - remainingHeight : 0);
} else {
- measureChildWithMargins(child, widthSpec, widthPadding, heightSpec, heightUsed);
+ measureChildWithMargins(child, widthSpec, 0, heightSpec, heightUsed);
}
heightUsed += child.getMeasuredHeight();
}
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 7a8c5c8a7b36..ebc6cd7dec6f 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -106,6 +106,11 @@ static jint saveUnclippedLayer(jlong canvasHandle, jint l, jint t, jint r, jint
return reinterpret_cast<jint>(get_canvas(canvasHandle)->saveUnclippedLayer(l, t, r, b));
}
+static void restoreUnclippedLayer(jlong canvasHandle, jint saveCount, jlong paintHandle) {
+ Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+ get_canvas(canvasHandle)->restoreUnclippedLayer(saveCount, *paint);
+}
+
static bool restore(jlong canvasHandle) {
Canvas* canvas = get_canvas(canvasHandle);
if (canvas->getSaveCount() <= 1) {
@@ -668,6 +673,7 @@ static const JNINativeMethod gMethods[] = {
{"nSaveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
{"nSaveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
{"nSaveUnclippedLayer","(JIIII)I", (void*) CanvasJNI::saveUnclippedLayer},
+ {"nRestoreUnclippedLayer","(JIJ)V", (void*) CanvasJNI::restoreUnclippedLayer},
{"nGetSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
{"nRestore","(J)Z", (void*) CanvasJNI::restore},
{"nRestoreToCount","(JI)V", (void*) CanvasJNI::restoreToCount},
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 36eb4c46faa8..4874c4199eaa 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2374,6 +2374,12 @@ enum PageId {
// Settings > Apps and notifications > Notifications > Gentle notifications
GENTLE_NOTIFICATIONS_SCREEN = 1715;
+ // OPEN: Settings > Display > Dark Theme
+ // CATEGORY: SETTINGS
+ // OS: Q
+ // Note: Only shows up on first time toggle
+ DIALOG_DARK_UI_INFO = 1740;
+
// OPEN: Settings > System > Gestures > Global Actions Panel
// CATEGORY: SETTINGS
// OS: Q
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 142e2a4e7a5d..1c1225b002db 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -904,9 +904,9 @@
android:backgroundPermission="android.permission.ACCESS_BACKGROUND_LOCATION"
android:protectionLevel="dangerous|instant" />
- <!-- Allows an app to access location in the background. If you
- are requesting this, you should also request {@link #ACCESS_FINE_LOCATION}.
- Requesting this by itself is not sufficient to give you
+ <!-- Allows an app to access location in the background. If you're requesting this permission,
+ you must also request either {@link #ACCESS_COARSE_LOCATION} or
+ {@link #ACCESS_FINE_LOCATION}. Requesting this permission by itself doesn't give you
location access.
<p>Protection level: dangerous
-->
diff --git a/core/res/res/drawable/list_divider_material.xml b/core/res/res/drawable/list_divider_material.xml
index 658a59d57330..e4c12fb1ad4e 100644
--- a/core/res/res/drawable/list_divider_material.xml
+++ b/core/res/res/drawable/list_divider_material.xml
@@ -15,8 +15,8 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="?attr/colorForeground">
- <solid android:color="#1f000000" />
+ android:tint="?attr/colorListDivider">
+ <solid android:color="?attr/opacityListDivider" />
<size
android:height="1dp"
android:width="1dp" />
diff --git a/core/res/res/values-night/themes_device_defaults.xml b/core/res/res/values-night/themes_device_defaults.xml
index b8bc17f2a232..8ba2c604ea6b 100644
--- a/core/res/res/values-night/themes_device_defaults.xml
+++ b/core/res/res/values-night/themes_device_defaults.xml
@@ -58,8 +58,10 @@ easier.
<item name="colorPrimary">@color/primary_dark_device_default_settings</item>
<item name="colorPrimaryDark">@color/primary_dark_device_default_settings</item>
<item name="colorBackground">@color/primary_dark_device_default_settings</item>
+ <item name="colorEdgeEffect">@color/edge_effect_device_default_dark</item>
- <item name="listDivider">@color/list_divider_color_dark</item>
+ <item name="colorListDivider">@color/list_divider_color_dark</item>
+ <item name="opacityListDivider">@color/list_divider_opacity_device_default_dark</item>
</style>
<style name="Theme.DeviceDefault.Settings.DialogBase" parent="Theme.Material.BaseDialog">
@@ -86,5 +88,4 @@ easier.
<style name="Theme.DeviceDefault.Resolver" parent="Theme.DeviceDefault.ResolverCommon">
<item name="windowLightNavigationBar">false</item>
</style>
-
</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index dbde79b74d4f..81accdf82b00 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -89,6 +89,10 @@
<attr name="backgroundDimEnabled" format="boolean" />
<!-- Color of background imagery used for popup windows. -->
<attr name="colorPopupBackground" format="color" />
+ <!-- Color used for list divider. -->
+ <attr name="colorListDivider" format="color" />
+ <!-- Opacity used for list divider. -->
+ <attr name="opacityListDivider" format="color" />
<!-- =========== -->
<!-- Text styles -->
diff --git a/core/res/res/values/colors_device_defaults.xml b/core/res/res/values/colors_device_defaults.xml
index 112f98e5ef35..7a8f411992ce 100644
--- a/core/res/res/values/colors_device_defaults.xml
+++ b/core/res/res/values/colors_device_defaults.xml
@@ -48,8 +48,14 @@
<color name="list_divider_color_light">#ffdadce0</color>
<color name="list_divider_color_dark">#85ffffff</color>
- <color name="loading_gradient_background_color_dark">#2D3033</color>
- <color name="loading_gradient_background_color_light">#DADCE0</color>
- <color name="loading_gradient_highlight_color_dark">#3C4043</color>
+ <color name="list_divider_opacity_device_default_light">@android:color/white</color>
+ <color name="list_divider_opacity_device_default_dark">@android:color/white</color>
+
+ <color name="loading_gradient_background_color_dark">#44484C</color>
+ <color name="loading_gradient_background_color_light">#F8F9FA</color>
+ <color name="loading_gradient_highlight_color_dark">#4D5155</color>
<color name="loading_gradient_highlight_color_light">#F1F3F4</color>
+
+ <color name="edge_effect_device_default_light">@android:color/black</color>
+ <color name="edge_effect_device_default_dark">@android:color/white</color>
</resources>
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index 2966aff6a9da..d357f0102777 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -149,4 +149,7 @@
<color name="autofill_background_material_dark">@color/material_blue_grey_900</color>
<color name="autofill_background_material_light">@color/material_grey_50</color>
+ <!-- List divider opacity -->
+ <color name="list_divider_opacity_material">#1f000000</color>
+
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0daebd76daf4..2de539721195 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3457,7 +3457,7 @@
<!-- Flag indicating whether the assist disclosure can be disabled using
ASSIST_DISCLOSURE_ENABLED. -->
- <bool name="config_allowDisablingAssistDisclosure">false</bool>
+ <bool name="config_allowDisablingAssistDisclosure">true</bool>
<!-- True if the device supports system navigation keys. -->
<bool name="config_supportSystemNavigationKeys">false</bool>
diff --git a/core/res/res/values/locale_config.xml b/core/res/res/values/locale_config.xml
index d6c0a108cffa..3c65caf074be 100644
--- a/core/res/res/values/locale_config.xml
+++ b/core/res/res/values/locale_config.xml
@@ -78,6 +78,7 @@
<item>ar-YE</item> <!-- Arabic (Yemen) -->
<item>ar-YE-u-nu-latn</item> <!-- Arabic (Yemen, Western Digits) -->
<item>as-IN</item> <!-- Assamese (India) -->
+ <item>as-IN-u-nu-latn</item> <!-- Assamese (India, Western Digits) -->
<item>asa-TZ</item> <!-- Asu (Tanzania) -->
<item>ast-ES</item> <!-- Asturian (Spain) -->
<item>az-Cyrl-AZ</item> <!-- Azerbaijani (Cyrillic, Azerbaijan) -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 37678dd42512..5b917cc4fdf1 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3614,7 +3614,7 @@
<!-- Message of notification shown when contaminant is detected on the USB port. [CHAR LIMIT=NONE] -->
<string name="usb_contaminant_detected_message">USB port is automatically disabled. Tap to learn more.</string>
<!-- Title of notification shown when contaminant is no longer detected on the USB port. [CHAR LIMIT=NONE] -->
- <string name="usb_contaminant_not_detected_title">Safe to use USB port</string>
+ <string name="usb_contaminant_not_detected_title">OK to use USB port</string>
<!-- Message of notification shown when contaminant is no longer detected on the USB port. [CHAR LIMIT=NONE] -->
<string name="usb_contaminant_not_detected_message">Phone no longer detects liquid or debris.</string>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 8015a5d5fbdd..628926231c65 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -1471,7 +1471,7 @@ easier.
<item name="colorSecondary">@color/secondary_device_default_settings_light</item>
<item name="colorAccent">@color/accent_device_default_light</item>
<item name="colorError">@color/error_color_device_default_light</item>
- <item name="colorEdgeEffect">@android:color/black</item>
+ <item name="colorEdgeEffect">@color/edge_effect_device_default_light</item>
<!-- Add white nav bar with divider that matches material -->
<item name="navigationBarDividerColor">@color/navigation_bar_divider_device_default_settings</item>
@@ -1488,7 +1488,8 @@ easier.
<!-- Progress bar attributes -->
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
- <item name="listDivider">@color/list_divider_color_light</item>
+ <item name="colorListDivider">@color/list_divider_color_light</item>
+ <item name="opacityListDivider">@color/list_divider_opacity_device_default_light</item>
</style>
<!-- @hide DeviceDefault theme for a window that should use Settings theme colors
@@ -1677,8 +1678,11 @@ easier.
<item name="colorControlActivated">?attr/colorControlHighlight</item>
<item name="listPreferredItemPaddingStart">?attr/dialogPreferredPadding</item>
<item name="listPreferredItemPaddingEnd">?attr/dialogPreferredPadding</item>
- <item name="navigationBarColor">?attr/colorBackgroundFloating</item>
- <item name="navigationBarDividerColor">@color/chooser_row_divider</item>
+ <item name="navigationBarColor">@android:color/transparent</item>
+ </style>
+
+ <style name="Theme.DeviceDefault.Resolver" parent="Theme.DeviceDefault.ResolverCommon">
+ <item name="windowLightNavigationBar">true</item>
</style>
<style name="Animation.DeviceDefault.Activity.Resolver" parent="Animation.DeviceDefault.Activity">
@@ -1689,10 +1693,6 @@ easier.
<item name="taskOpenExitAnimation">@anim/resolver_close_anim</item>
</style>
- <style name="Theme.DeviceDefault.Resolver" parent="Theme.DeviceDefault.ResolverCommon">
- <item name="windowLightNavigationBar">true</item>
- </style>
-
<!-- @hide DeviceDefault themes for the autofill FillUi -->
<style name="Theme.DeviceDefault.Autofill" />
<style name="Theme.DeviceDefault.Light.Autofill" />
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 6337db1905c9..ce2938952d61 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -53,6 +53,8 @@ please see themes_device_defaults.xml.
<item name="backgroundDimAmount">0.6</item>
<item name="colorError">@color/error_color_material_dark</item>
<item name="colorPopupBackground">?attr/colorBackground</item>
+ <item name="colorListDivider">?attr/colorForeground</item>
+ <item name="opacityListDivider">@color/list_divider_opacity_material</item>
<!-- Text styles -->
<item name="textAppearance">@style/TextAppearance.Material</item>
@@ -424,6 +426,8 @@ please see themes_device_defaults.xml.
<item name="backgroundDimAmount">0.6</item>
<item name="colorError">@color/error_color_material_light</item>
<item name="colorPopupBackground">?attr/colorBackground</item>
+ <item name="colorListDivider">?attr/colorForeground</item>
+ <item name="opacityListDivider">@color/list_divider_opacity_material</item>
<!-- Text styles -->
<item name="textAppearance">@style/TextAppearance.Material</item>
diff --git a/core/tests/bugreports/src/android/server/bugreports/BugreportManagerTest.java b/core/tests/bugreports/src/android/server/bugreports/BugreportManagerTest.java
index 220f854c337a..c72707db9560 100644
--- a/core/tests/bugreports/src/android/server/bugreports/BugreportManagerTest.java
+++ b/core/tests/bugreports/src/android/server/bugreports/BugreportManagerTest.java
@@ -88,7 +88,9 @@ public class BugreportManagerTest {
@Test
public void normalFlow_wifi() throws Exception {
BugreportCallbackImpl callback = new BugreportCallbackImpl();
- mBrm.startBugreport(mBugreportFd, mScreenshotFd, wifi(), mExecutor, callback);
+ // wifi bugreport does not take screenshot
+ mBrm.startBugreport(mBugreportFd, null /*screenshotFd = null*/, wifi(),
+ mExecutor, callback);
waitTillDoneOrTimeout(callback);
assertThat(callback.isDone()).isTrue();
@@ -99,13 +101,15 @@ public class BugreportManagerTest {
// of mBugreportFd.
assertThat(callback.getErrorCode()).isEqualTo(
BugreportCallback.BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
- assertFdsAreClosed(mBugreportFd, mScreenshotFd);
+ assertFdsAreClosed(mBugreportFd);
}
@Test
public void normalFlow_interactive() throws Exception {
BugreportCallbackImpl callback = new BugreportCallbackImpl();
- mBrm.startBugreport(mBugreportFd, mScreenshotFd, interactive(), mExecutor, callback);
+ // interactive bugreport does not take screenshot
+ mBrm.startBugreport(mBugreportFd, null /*screenshotFd = null*/, interactive(),
+ mExecutor, callback);
waitTillDoneOrTimeout(callback);
assertThat(callback.isDone()).isTrue();
@@ -113,7 +117,7 @@ public class BugreportManagerTest {
assertThat(callback.hasReceivedProgress()).isTrue();
assertThat(callback.getErrorCode()).isEqualTo(
BugreportCallback.BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
- assertFdsAreClosed(mBugreportFd, mScreenshotFd);
+ assertFdsAreClosed(mBugreportFd);
}
@Test
diff --git a/core/tests/coretests/src/android/text/EmojiTest.java b/core/tests/coretests/src/android/text/EmojiTest.java
index 194899415e0d..7a42731992d1 100644
--- a/core/tests/coretests/src/android/text/EmojiTest.java
+++ b/core/tests/coretests/src/android/text/EmojiTest.java
@@ -40,7 +40,7 @@ import org.junit.runner.RunWith;
public class EmojiTest {
@Test
- public void testIsNewEmoji_Emoji5() {
+ public void testIsNewEmoji_Emoji() {
// each row in the data is the range of emoji
final int[][][] data = new int[][][]{
{ // EMOJI 5
@@ -66,6 +66,24 @@ public class EmojiTest {
{0x1F9B0, 0x1F9B9},
{0x1F9C1, 0x1F9C2},
{0x1F9E7, 0x1F9FF},
+ },
+ { // EMOJI 12
+ {0x1F6D5, 0x1F6D5},
+ {0x1F6FA, 0x1F6FA},
+ {0x1F93F, 0x1F93F},
+ {0x1F971, 0x1F971},
+ {0x1F97B, 0x1F97B},
+ {0x1F7E0, 0x1F7EB},
+ {0x1F90D, 0x1F90F},
+ {0x1F9A5, 0x1F9AA},
+ {0x1F9AE, 0x1F9AF},
+ {0x1F9BA, 0x1F9BF},
+ {0x1F9C3, 0x1F9CA},
+ {0x1F9CD, 0x1F9CF},
+ {0x1FA70, 0x1FA73},
+ {0x1FA78, 0x1FA7A},
+ {0x1FA80, 0x1FA82},
+ {0x1FA90, 0x1FA95}
}
};
diff --git a/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml
index 5cfae1170097..e24f26c16310 100644
--- a/data/etc/hiddenapi-package-whitelist.xml
+++ b/data/etc/hiddenapi-package-whitelist.xml
@@ -55,5 +55,6 @@ platform cert need to be included, as apps signed with the platform cert are exe
<hidden-api-whitelisted-app package="com.android.storagemanager" />
<hidden-api-whitelisted-app package="com.android.systemui.plugins" />
<hidden-api-whitelisted-app package="com.android.terminal" />
+ <hidden-api-whitelisted-app package="com.android.wallpaper" />
<hidden-api-whitelisted-app package="jp.co.omronsoft.openwnn" />
</config>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index c54208b96031..a16d5a72e19d 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -194,14 +194,12 @@
targetSdk="16">
<new-permission name="android.permission.WRITE_CALL_LOG" />
</split-permission>
- <!-- STOPSHIP(b/118882117): change targetSdk to Q when SDK version finalised -->
<split-permission name="android.permission.ACCESS_FINE_LOCATION"
- targetSdk="10000">
+ targetSdk="29">
<new-permission name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</split-permission>
- <!-- STOPSHIP(b/118882117): change targetSdk to Q when SDK version finalised -->
<split-permission name="android.permission.ACCESS_COARSE_LOCATION"
- targetSdk="10000">
+ targetSdk="29">
<new-permission name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</split-permission>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index e524216d5c55..b3856d501c72 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -264,6 +264,8 @@ applications that come with the platform
<permission name="android.permission.INSTALL_DYNAMIC_SYSTEM"/>
<permission name="android.permission.INSTALL_LOCATION_PROVIDER"/>
<permission name="android.permission.INSTALL_PACKAGES"/>
+ <!-- Needed for test only -->
+ <permission name="android.permission.INTERACT_ACROSS_PROFILES"/>
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.LOCAL_MAC_ADDRESS"/>
<permission name="android.permission.MANAGE_ACCESSIBILITY"/>
@@ -314,6 +316,8 @@ applications that come with the platform
<permission name="android.permission.SET_WALLPAPER" />
<permission name="android.permission.SET_WALLPAPER_COMPONENT" />
<permission name="android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE" />
+ <!-- Permission required to test ExplicitHealthCheckServiceImpl. -->
+ <permission name="android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE"/>
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index d4d5ae7bdddb..5648b854db40 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -559,6 +559,16 @@ public class Canvas extends BaseCanvas {
}
/**
+ * @hide
+ * @param saveCount The save level to restore to.
+ * @param paint This is copied and is applied to the area within the unclipped layer's
+ * bounds (i.e. equivalent to a drawPaint()) before restore() is called.
+ */
+ public void restoreUnclippedLayer(int saveCount, Paint paint) {
+ nRestoreUnclippedLayer(mNativeCanvasWrapper, saveCount, paint.getNativeInstance());
+ }
+
+ /**
* Helper version of saveLayer() that takes 4 values rather than a RectF.
*
* As of API Level API level {@value Build.VERSION_CODES#P} the only valid
@@ -1398,6 +1408,9 @@ public class Canvas extends BaseCanvas {
@CriticalNative
private static native int nSaveUnclippedLayer(long nativeCanvas, int l, int t, int r, int b);
@CriticalNative
+ private static native void nRestoreUnclippedLayer(long nativeCanvas, int saveCount,
+ long nativePaint);
+ @CriticalNative
private static native boolean nRestore(long canvasHandle);
@CriticalNative
private static native void nRestoreToCount(long canvasHandle, int saveCount);
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 297153d09eca..32f2fc22acad 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -1930,11 +1930,11 @@ public class GradientDrawable extends Drawable {
public float[] mTempPositions; // no need to copy
@UnsupportedAppUsage
public float[] mPositions;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
+ @UnsupportedAppUsage(trackingBug = 124050917)
public int mStrokeWidth = -1; // if >= 0 use stroking.
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
+ @UnsupportedAppUsage(trackingBug = 124050917)
public float mStrokeDashWidth = 0.0f;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
+ @UnsupportedAppUsage(trackingBug = 124050917)
public float mStrokeDashGap = 0.0f;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 124050917)
public float mRadius = 0.0f; // use this if mRadiusArray is null
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 1b515ad41e68..d20aecaaf0f6 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -778,8 +778,6 @@ const ResolvedBag* AssetManager2::GetBag(uint32_t resid) {
}
const ResolvedBag* AssetManager2::GetBag(uint32_t resid, std::vector<uint32_t>& child_resids) {
- ATRACE_NAME("AssetManager::GetBag");
-
auto cached_iter = cached_bags_.find(resid);
if (cached_iter != cached_bags_.end()) {
return cached_iter->second.get();
diff --git a/libs/hwui/DisplayListOps.in b/libs/hwui/DisplayListOps.in
index 14e3a32817a0..2deb5657c877 100644
--- a/libs/hwui/DisplayListOps.in
+++ b/libs/hwui/DisplayListOps.in
@@ -26,7 +26,8 @@ X(ClipPath)
X(ClipRect)
X(ClipRRect)
X(ClipRegion)
-X(DrawPaint)
+X(DrawPaint)
+X(DrawBehind)
X(DrawPath)
X(DrawRect)
X(DrawRegion)
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 85947665839a..e58fbbe8e667 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -20,6 +20,7 @@
#include "SkAndroidFrameworkUtils.h"
#include "SkCanvas.h"
+#include "SkCanvasPriv.h"
#include "SkData.h"
#include "SkDrawShadowInfo.h"
#include "SkImage.h"
@@ -187,6 +188,12 @@ struct DrawPaint final : Op {
SkPaint paint;
void draw(SkCanvas* c, const SkMatrix&) const { c->drawPaint(paint); }
};
+struct DrawBehind final : Op {
+ static const auto kType = Type::DrawBehind;
+ DrawBehind(const SkPaint& paint) : paint(paint) {}
+ SkPaint paint;
+ void draw(SkCanvas* c, const SkMatrix&) const { SkCanvasPriv::DrawBehind(c, paint); }
+};
struct DrawPath final : Op {
static const auto kType = Type::DrawPath;
DrawPath(const SkPath& path, const SkPaint& paint) : path(path), paint(paint) {}
@@ -565,6 +572,9 @@ void DisplayListData::clipRegion(const SkRegion& region, SkClipOp op) {
void DisplayListData::drawPaint(const SkPaint& paint) {
this->push<DrawPaint>(0, paint);
}
+void DisplayListData::drawBehind(const SkPaint& paint) {
+ this->push<DrawBehind>(0, paint);
+}
void DisplayListData::drawPath(const SkPath& path, const SkPaint& paint) {
this->push<DrawPath>(0, path, paint);
}
@@ -834,6 +844,9 @@ void RecordingCanvas::onClipRegion(const SkRegion& region, SkClipOp op) {
void RecordingCanvas::onDrawPaint(const SkPaint& paint) {
fDL->drawPaint(paint);
}
+void RecordingCanvas::onDrawBehind(const SkPaint& paint) {
+ fDL->drawBehind(paint);
+}
void RecordingCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
fDL->drawPath(path, paint);
}
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 3a76ca1137a5..7269bcad3d7a 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -89,6 +89,7 @@ private:
void clipRegion(const SkRegion&, SkClipOp);
void drawPaint(const SkPaint&);
+ void drawBehind(const SkPaint&);
void drawPath(const SkPath&, const SkPaint&);
void drawRect(const SkRect&, const SkPaint&);
void drawRegion(const SkRegion&, const SkPaint&);
@@ -157,6 +158,7 @@ public:
void onClipRegion(const SkRegion&, SkClipOp) override;
void onDrawPaint(const SkPaint&) override;
+ void onDrawBehind(const SkPaint&) override;
void onDrawPath(const SkPath&, const SkPaint&) override;
void onDrawRect(const SkRect&, const SkPaint&) override;
void onDrawRegion(const SkRegion&, const SkPaint&) override;
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index f328a5399cbb..bebda8527def 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -26,6 +26,7 @@
#include <SkAndroidFrameworkUtils.h>
#include <SkAnimatedImage.h>
+#include <SkCanvasPriv.h>
#include <SkCanvasStateUtils.h>
#include <SkColorFilter.h>
#include <SkDeque.h>
@@ -191,6 +192,18 @@ int SkiaCanvas::saveUnclippedLayer(int left, int top, int right, int bottom) {
return SkAndroidFrameworkUtils::SaveBehind(mCanvas, &bounds);
}
+void SkiaCanvas::restoreUnclippedLayer(int restoreCount, const SkPaint& paint) {
+
+ while (mCanvas->getSaveCount() > restoreCount + 1) {
+ this->restore();
+ }
+
+ if (mCanvas->getSaveCount() == restoreCount + 1) {
+ SkCanvasPriv::DrawBehind(mCanvas, *filterPaint(paint));
+ this->restore();
+ }
+}
+
class SkiaCanvas::Clip {
public:
Clip(const SkRect& rect, SkClipOp op, const SkMatrix& m)
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index 3fe2bce06b41..bbe91eb2fbc4 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -69,6 +69,7 @@ public:
virtual int save(SaveFlags::Flags flags) override;
virtual void restore() override;
virtual void restoreToCount(int saveCount) override;
+ virtual void restoreUnclippedLayer(int saveCount, const SkPaint& paint) override;
virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
SaveFlags::Flags flags) override;
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 11e8579a481f..ac8db216b059 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -191,6 +191,7 @@ public:
virtual int save(SaveFlags::Flags flags) = 0;
virtual void restore() = 0;
virtual void restoreToCount(int saveCount) = 0;
+ virtual void restoreUnclippedLayer(int saveCount, const SkPaint& paint) = 0;
virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
SaveFlags::Flags flags) = 0;
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index ccc1701dcc0b..1f9ab5a242b4 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -176,7 +176,7 @@ bool SkiaPipeline::createOrUpdateLayer(RenderNode* node, const DamageAccumulator
// position
Matrix4 windowTransform;
damageAccumulator.computeCurrentTransform(&windowTransform);
- node->getSkiaLayer()->inverseTransformInWindow = windowTransform;
+ node->getSkiaLayer()->inverseTransformInWindow.loadInverse(windowTransform);
} else {
String8 cachesOutput;
mRenderThread.cacheManager().dumpMemoryUsage(cachesOutput,
diff --git a/libs/protoutil/include/android/util/ProtoOutputStream.h b/libs/protoutil/include/android/util/ProtoOutputStream.h
index 60d03180c09d..a6af4757a140 100644
--- a/libs/protoutil/include/android/util/ProtoOutputStream.h
+++ b/libs/protoutil/include/android/util/ProtoOutputStream.h
@@ -19,6 +19,7 @@
#include <cstdint>
#include <string>
+#include <vector>
#include <android/util/EncodedBuffer.h>
@@ -124,6 +125,7 @@ public:
sp<ProtoReader> data(); // Get the reader apis of the data.
bool flush(int fd); // Flush data directly to a file descriptor.
bool serializeToString(std::string* out); // Serializes the proto to a string.
+ bool serializeToVector(std::vector<uint8_t>* out); // Serializes the proto to a vector<uint8_t>.
/**
* Clears the ProtoOutputStream so the buffer can be reused instead of deallocation/allocation again.
diff --git a/libs/protoutil/src/ProtoOutputStream.cpp b/libs/protoutil/src/ProtoOutputStream.cpp
index 98a68c6482b5..6cfa357b580b 100644
--- a/libs/protoutil/src/ProtoOutputStream.cpp
+++ b/libs/protoutil/src/ProtoOutputStream.cpp
@@ -454,7 +454,6 @@ ProtoOutputStream::serializeToString(std::string* out)
if (out == nullptr) return false;
if (!compact()) return false;
-
sp<ProtoReader> reader = mBuffer->read();
out->reserve(reader->size());
while (reader->hasNext()) {
@@ -465,6 +464,23 @@ ProtoOutputStream::serializeToString(std::string* out)
return true;
}
+bool
+ProtoOutputStream::serializeToVector(std::vector<uint8_t>* out)
+{
+ if (out == nullptr) return false;
+ if (!compact()) return false;
+
+ sp<ProtoReader> reader = mBuffer->read();
+ out->reserve(reader->size());
+ while (reader->hasNext()) {
+ const uint8_t* buf = reader->readBuffer();
+ size_t size = reader->currentToRead();
+ out->insert(out->end(), buf, buf + size);
+ reader->move(size);
+ }
+ return true;
+}
+
sp<ProtoReader>
ProtoOutputStream::data()
{
diff --git a/libs/protoutil/tests/ProtoOutputStream_test.cpp b/libs/protoutil/tests/ProtoOutputStream_test.cpp
index 6282fd553eae..9b768b73d22b 100644
--- a/libs/protoutil/tests/ProtoOutputStream_test.cpp
+++ b/libs/protoutil/tests/ProtoOutputStream_test.cpp
@@ -132,6 +132,53 @@ TEST(ProtoOutputStreamTest, SerializeToStringPrimitives) {
EXPECT_EQ(primitives.val_enum(), PrimitiveProto_Count_TWO);
}
+TEST(ProtoOutputStreamTest, SerializeToVectorPrimitives) {
+ std::string s = "hello";
+ const char b[5] = { 'a', 'p', 'p', 'l', 'e' };
+
+ ProtoOutputStream proto;
+ EXPECT_TRUE(proto.write(FIELD_TYPE_INT32 | PrimitiveProto::kValInt32FieldNumber, 123));
+ EXPECT_TRUE(proto.write(FIELD_TYPE_INT64 | PrimitiveProto::kValInt64FieldNumber, -1LL));
+ EXPECT_TRUE(proto.write(FIELD_TYPE_FLOAT | PrimitiveProto::kValFloatFieldNumber, -23.5f));
+ EXPECT_TRUE(proto.write(FIELD_TYPE_DOUBLE | PrimitiveProto::kValDoubleFieldNumber, 324.5));
+ EXPECT_TRUE(proto.write(FIELD_TYPE_UINT32 | PrimitiveProto::kValUint32FieldNumber, 3424));
+ EXPECT_TRUE(proto.write(FIELD_TYPE_UINT64 | PrimitiveProto::kValUint64FieldNumber, 57LL));
+ EXPECT_TRUE(proto.write(FIELD_TYPE_FIXED32 | PrimitiveProto::kValFixed32FieldNumber, -20));
+ EXPECT_TRUE(proto.write(FIELD_TYPE_FIXED64 | PrimitiveProto::kValFixed64FieldNumber, -37LL));
+ EXPECT_TRUE(proto.write(FIELD_TYPE_BOOL | PrimitiveProto::kValBoolFieldNumber, true));
+ EXPECT_TRUE(proto.write(FIELD_TYPE_STRING | PrimitiveProto::kValStringFieldNumber, s));
+ EXPECT_TRUE(proto.write(FIELD_TYPE_BYTES | PrimitiveProto::kValBytesFieldNumber, b, 5));
+ EXPECT_TRUE(proto.write(FIELD_TYPE_SFIXED32 | PrimitiveProto::kValSfixed32FieldNumber, 63));
+ EXPECT_TRUE(proto.write(FIELD_TYPE_SFIXED64 | PrimitiveProto::kValSfixed64FieldNumber, -54));
+ EXPECT_TRUE(proto.write(FIELD_TYPE_SINT32 | PrimitiveProto::kValSint32FieldNumber, -533));
+ EXPECT_TRUE(proto.write(FIELD_TYPE_SINT64 | PrimitiveProto::kValSint64FieldNumber, -61224762453LL));
+ EXPECT_TRUE(proto.write(FIELD_TYPE_ENUM | PrimitiveProto::kValEnumFieldNumber, 2));
+
+ PrimitiveProto primitives;
+ std::vector<uint8_t> vec;
+ ASSERT_TRUE(proto.serializeToVector(&vec));
+
+ std::string serialized(vec.data(), vec.data() + vec.size());
+ ASSERT_TRUE(primitives.ParseFromString(serialized));
+
+ EXPECT_EQ(primitives.val_int32(), 123);
+ EXPECT_EQ(primitives.val_int64(), -1);
+ EXPECT_EQ(primitives.val_float(), -23.5f);
+ EXPECT_EQ(primitives.val_double(), 324.5f);
+ EXPECT_EQ(primitives.val_uint32(), 3424);
+ EXPECT_EQ(primitives.val_uint64(), 57);
+ EXPECT_EQ(primitives.val_fixed32(), -20);
+ EXPECT_EQ(primitives.val_fixed64(), -37);
+ EXPECT_EQ(primitives.val_bool(), true);
+ EXPECT_THAT(primitives.val_string(), StrEq(s.c_str()));
+ EXPECT_THAT(primitives.val_bytes(), StrEq("apple"));
+ EXPECT_EQ(primitives.val_sfixed32(), 63);
+ EXPECT_EQ(primitives.val_sfixed64(), -54);
+ EXPECT_EQ(primitives.val_sint32(), -533);
+ EXPECT_EQ(primitives.val_sint64(), -61224762453LL);
+ EXPECT_EQ(primitives.val_enum(), PrimitiveProto_Count_TWO);
+}
+
TEST(ProtoOutputStreamTest, Complex) {
std::string name1 = "cat";
std::string name2 = "dog";
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 04e7bab0542b..e8905143eb37 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -360,7 +360,7 @@ public class GpsNetInitiatedHandler {
/**
* Posts a notification in the status bar using the contents in {@code notif} object.
*/
- public synchronized void setNiNotification(GpsNiNotification notif) {
+ private synchronized void setNiNotification(GpsNiNotification notif) {
NotificationManager notificationManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager == null) {
@@ -541,35 +541,26 @@ public class GpsNetInitiatedHandler {
*/
static private String decodeString(String original, boolean isHex, int coding)
{
- if (coding == GPS_ENC_NONE) {
+ if (coding == GPS_ENC_NONE || coding == GPS_ENC_UNKNOWN) {
return original;
}
- String decoded = original;
byte[] input = stringToByteArray(original, isHex);
switch (coding) {
- case GPS_ENC_SUPL_GSM_DEFAULT:
- decoded = decodeGSMPackedString(input);
- break;
+ case GPS_ENC_SUPL_GSM_DEFAULT:
+ return decodeGSMPackedString(input);
- case GPS_ENC_SUPL_UTF8:
- decoded = decodeUTF8String(input);
- break;
+ case GPS_ENC_SUPL_UTF8:
+ return decodeUTF8String(input);
- case GPS_ENC_SUPL_UCS2:
- decoded = decodeUCS2String(input);
- break;
+ case GPS_ENC_SUPL_UCS2:
+ return decodeUCS2String(input);
- case GPS_ENC_UNKNOWN:
- decoded = original;
- break;
-
- default:
- Log.e(TAG, "Unknown encoding " + coding + " for NI text " + original);
- break;
+ default:
+ Log.e(TAG, "Unknown encoding " + coding + " for NI text " + original);
+ return original;
}
- return decoded;
}
// change this to configure notification display
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index a8f313b9df8a..dc3041fb4878 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -400,7 +400,7 @@ public final class AudioAttributes implements Parcelable {
/**
* Indicates that the audio may be captured by any app.
*
- * For privacy, the following usages can not be recorded: VOICE_COMMUNICATION*,
+ * For privacy, the following usages cannot be recorded: VOICE_COMMUNICATION*,
* USAGE_NOTIFICATION*, USAGE_ASSISTANCE* and USAGE_ASSISTANT.
*
* On {@link android.os.Build.VERSION_CODES#Q}, this means only {@link #USAGE_UNKNOWN},
@@ -413,11 +413,11 @@ public final class AudioAttributes implements Parcelable {
/**
* Indicates that the audio may only be captured by system apps.
*
- * System apps can capture for many purposes like accessibility, user guidance...
+ * System apps can capture for many purposes like accessibility, live captions, user guidance...
* but abide to the following restrictions:
- * - the audio can not leave the device
- * - the audio can not be passed to a third party app
- * - the audio can not be recorded at a higher quality then 16kHz 16bit mono
+ * - the audio cannot leave the device
+ * - the audio cannot be passed to a third party app
+ * - the audio cannot be recorded at a higher quality than 16kHz 16bit mono
*
* See {@link Builder#setAllowedCapturePolicy}.
*/
diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java
index b3c2bb78862a..534d63b4cca0 100644
--- a/media/java/android/media/ThumbnailUtils.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -265,13 +265,10 @@ public class ThumbnailUtils {
}
}
- boolean isHeifFile = false;
-
if (mimeType.equals("image/heif")
|| mimeType.equals("image/heif-sequence")
|| mimeType.equals("image/heic")
|| mimeType.equals("image/heic-sequence")) {
- isHeifFile = true;
try (MediaMetadataRetriever retriever = new MediaMetadataRetriever()) {
retriever.setDataSource(file.getAbsolutePath());
bitmap = retriever.getThumbnailImageAtIndex(-1,
@@ -298,11 +295,8 @@ public class ThumbnailUtils {
if (bitmap == null) {
bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(file), resizer);
- // Use ImageDecoder to do full image decode of heif format file
- // will have right orientation. Don't rotate the bitmap again.
- if (isHeifFile) {
- return bitmap;
- }
+ // Use ImageDecoder to do full file decoding, we don't need to handle the orientation
+ return bitmap;
}
// Transform the bitmap if the orientation of the image is not 0.
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index 2f03d26830f2..a82c78fad271 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -91,6 +91,20 @@ public class AudioMix {
*/
public static final int ROUTE_FLAG_LOOP_BACK = 0x1 << 1;
+ /**
+ * An audio mix behavior where the targeted audio is played unaffected but a copy is
+ * accessible for capture through {@link AudioRecord}.
+ *
+ * Only capture of playback is supported, not capture of capture.
+ * Use concurrent capture instead to capture what is captured by other apps.
+ *
+ * The captured audio is an approximation of the played audio.
+ * Effects and volume are not applied, and track are mixed with different delay then in the HAL.
+ * As a result, this API is not suitable for echo cancelling.
+ * @hide
+ */
+ public static final int ROUTE_FLAG_LOOP_BACK_RENDER = ROUTE_FLAG_LOOP_BACK | ROUTE_FLAG_RENDER;
+
private static final int ROUTE_FLAG_SUPPORTED = ROUTE_FLAG_RENDER | ROUTE_FLAG_LOOP_BACK;
// MIX_TYPE_* values to keep in sync with frameworks/av/include/media/AudioPolicy.h
@@ -125,6 +139,15 @@ public class AudioMix {
*/
public static final int MIX_STATE_MIXING = 1;
+ /** Maximum sampling rate for privileged playback capture*/
+ private static final int PRIVILEDGED_CAPTURE_MAX_SAMPLE_RATE = 16000;
+
+ /** Maximum channel number for privileged playback capture*/
+ private static final int PRIVILEDGED_CAPTURE_MAX_CHANNEL_NUMBER = 1;
+
+ /** Maximum channel number for privileged playback capture*/
+ private static final int PRIVILEDGED_CAPTURE_MAX_BYTES_PER_SAMPLE = 2;
+
/**
* The current mixing state.
* @return one of {@link #MIX_STATE_DISABLED}, {@link #MIX_STATE_IDLE},
@@ -140,7 +163,8 @@ public class AudioMix {
return mRouteFlags;
}
- AudioFormat getFormat() {
+ /** @hide */
+ public AudioFormat getFormat() {
return mFormat;
}
@@ -182,6 +206,31 @@ public class AudioMix {
return true;
}
+ /** @return an error string if the format would not allow Privileged playbackCapture
+ * null otherwise
+ * @hide */
+ public static String canBeUsedForPrivilegedCapture(AudioFormat format) {
+ int sampleRate = format.getSampleRate();
+ if (sampleRate > PRIVILEDGED_CAPTURE_MAX_SAMPLE_RATE || sampleRate <= 0) {
+ return "Privileged audio capture sample rate " + sampleRate
+ + " can not be over " + PRIVILEDGED_CAPTURE_MAX_SAMPLE_RATE + "kHz";
+ }
+ int channelCount = format.getChannelCount();
+ if (channelCount > PRIVILEDGED_CAPTURE_MAX_CHANNEL_NUMBER || channelCount <= 0) {
+ return "Privileged audio capture channel count " + channelCount + " can not be over "
+ + PRIVILEDGED_CAPTURE_MAX_CHANNEL_NUMBER;
+ }
+ int encoding = format.getEncoding();
+ if (!format.isPublicEncoding(encoding) || !format.isEncodingLinearPcm(encoding)) {
+ return "Privileged audio capture encoding " + encoding + "is not linear";
+ }
+ if (format.getBytesPerSample(encoding) > PRIVILEDGED_CAPTURE_MAX_BYTES_PER_SAMPLE) {
+ return "Privileged audio capture encoding " + encoding + " can not be over "
+ + PRIVILEDGED_CAPTURE_MAX_BYTES_PER_SAMPLE + " bytes per sample";
+ }
+ return null;
+ }
+
/** @hide */
@Override
public boolean equals(Object o) {
@@ -390,6 +439,12 @@ public class AudioMix {
}
}
}
+ if (mRule.allowPrivilegedPlaybackCapture()) {
+ String error = AudioMix.canBeUsedForPrivilegedCapture(mFormat);
+ if (error != null) {
+ throw new IllegalArgumentException(error);
+ }
+ }
return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceSystemType,
mDeviceAddress);
}
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index ed2fdae71fb0..c4afd95be9ac 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -365,6 +365,10 @@ public class AudioMixingRule {
/**
* Set if the audio of app that opted out of audio playback capture should be captured.
*
+ * Caller of this method with <code>true</code>, MUST abide to the restriction listed in
+ * {@link ALLOW_CAPTURE_BY_SYSTEM}, including but not limited to the captured audio
+ * can not leave the capturing app, and the quality is limited to 16k mono.
+ *
* The permission {@link CAPTURE_AUDIO_OUTPUT} or {@link CAPTURE_MEDIA_OUTPUT} is needed
* to ignore the opt-out.
*
diff --git a/packages/BackupRestoreConfirmation/res/values-eu/strings.xml b/packages/BackupRestoreConfirmation/res/values-eu/strings.xml
index ca89aa603e3f..3905a0b4d7be 100644
--- a/packages/BackupRestoreConfirmation/res/values-eu/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-eu/strings.xml
@@ -18,10 +18,10 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="backup_confirm_title" msgid="827563724209303345">"Babeskopia osoa"</string>
<string name="restore_confirm_title" msgid="5469365809567486602">"Leheneratze osoa"</string>
- <string name="backup_confirm_text" msgid="1878021282758896593">"Datu guztien babeskopia egitea eta konektatutako ordenagailu batean gordetzea eskatu da. Horretarako baimena eman nahi duzu?\n\nEz baduzu babeskopia egitea zeuk eskatu, ez eman eragiketarekin jarraitzeko baimena."</string>
+ <string name="backup_confirm_text" msgid="1878021282758896593">"Datu guztien babeskopia egitea eta konektatutako ordenagailu batean gordetzea eskatu da. Horretarako baimena eman nahi duzu?\n\nEz baduzu babeskopia egitea zuk eskatu, ez eman eragiketarekin jarraitzeko baimena."</string>
<string name="allow_backup_button_label" msgid="4217228747769644068">"Egin datuen babeskopia"</string>
<string name="deny_backup_button_label" msgid="6009119115581097708">"Ez egin babeskopia"</string>
- <string name="restore_confirm_text" msgid="7499866728030461776">"Konektatutako ordenagailu bateko datu guztiak leheneratzeko eskatu da. Horretarako baimena eman nahi duzu?\n\nEz baduzu leheneratzea zeuk eskatu, ez eman eragiketarekin jarraitzeko baimena. Eragiketa gauzatzen bada, gailuan dituzun datu guztiak ordeztuko dira!"</string>
+ <string name="restore_confirm_text" msgid="7499866728030461776">"Konektatutako ordenagailu bateko datu guztiak leheneratzeko eskatu da. Horretarako baimena eman nahi duzu?\n\nEz baduzu leheneratzea zuk eskatu, ez eman eragiketarekin jarraitzeko baimena. Eragiketa gauzatzen bada, gailuan dituzun datu guztiak ordeztuko dira!"</string>
<string name="allow_restore_button_label" msgid="3081286752277127827">"Leheneratu datuak"</string>
<string name="deny_restore_button_label" msgid="1724367334453104378">"Ez leheneratu"</string>
<string name="current_password_text" msgid="8268189555578298067">"Idatzi babeskopien uneko pasahitza behean:"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-hi/strings.xml b/packages/BackupRestoreConfirmation/res/values-hi/strings.xml
index ae9e7c397c92..2e53cb6388a0 100644
--- a/packages/BackupRestoreConfirmation/res/values-hi/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-hi/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="backup_confirm_title" msgid="827563724209303345">"पूर्ण सुरक्षा"</string>
- <string name="restore_confirm_title" msgid="5469365809567486602">"पूर्ण पुनर्स्‍थापना"</string>
+ <string name="backup_confirm_title" msgid="827563724209303345">"पूरा बैकअप"</string>
+ <string name="restore_confirm_title" msgid="5469365809567486602">"पूरी तरह से पुनर्स्‍थापना"</string>
<string name="backup_confirm_text" msgid="1878021282758896593">"कनेक्‍ट कि‍ए गए डेस्‍कटॉप कंप्‍यूटर से पूरे डेटा के बैकअप का अनुरोध कि‍या गया है. क्‍या आप इसकी अनुमति‍ देना चाहते हैं?\n\nअगर आपने बैकअप का अनुरोध नहीं कि‍या है, तो इस प्रक्रि‍या को जारी रखने की अनुमति‍ न दें."</string>
<string name="allow_backup_button_label" msgid="4217228747769644068">"मेरे डेटा का बैकअप लें"</string>
<string name="deny_backup_button_label" msgid="6009119115581097708">"बैकअप न लें"</string>
@@ -32,7 +32,7 @@
<string name="backup_enc_password_required" msgid="7889652203371654149">"चूंकि आपका डिवाइस एन्क्रिप्ट किया हुआ है, इसलिए आपको अपने बैकअप को एन्क्रिप्ट करना आवश्यक है. कृपया नीचे पासवर्ड डालें:"</string>
<string name="restore_enc_password_text" msgid="6140898525580710823">"अगर रिस्टोर किया गया डेटा सुरक्षित कि‍या गया है, तो कृपया नीचे पासवर्ड डालें:"</string>
<string name="toast_backup_started" msgid="550354281452756121">"सुरक्षित करना शुरु हो रहा है..."</string>
- <string name="toast_backup_ended" msgid="3818080769548726424">"सुरक्षित करना पूर्ण"</string>
+ <string name="toast_backup_ended" msgid="3818080769548726424">"बैकअप करना पूरा हुआ"</string>
<string name="toast_restore_started" msgid="7881679218971277385">"पुनर्स्‍थापना प्रारंभ हो रही है..."</string>
<string name="toast_restore_ended" msgid="1764041639199696132">"पुनर्स्‍थापना खत्म"</string>
<string name="toast_timeout" msgid="5276598587087626877">"काम नहीं हो सका. टाइम आउट हो गया"</string>
diff --git a/packages/CaptivePortalLogin/res/values-bs/strings.xml b/packages/CaptivePortalLogin/res/values-bs/strings.xml
index 60c153a06471..83b5067235e2 100644
--- a/packages/CaptivePortalLogin/res/values-bs/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-bs/strings.xml
@@ -18,7 +18,7 @@
<string name="ssl_error_unknown" msgid="4405203446079465859">"Nepoznata greška potvrde."</string>
<string name="ssl_security_warning_title" msgid="8768539813847504404">"Sigurnosno upozorenje"</string>
<string name="ssl_error_view_certificate" msgid="5722652540168339333">"Prikaži potvrdu"</string>
- <string name="ok" msgid="2817931639040794018">"UREDU"</string>
+ <string name="ok" msgid="2817931639040794018">"Uredu"</string>
<string name="page_info_address" msgid="1261481517455692363">"Adresa:"</string>
<string name="page_info" msgid="4416941086705172545">"Informacije o stranici"</string>
</resources>
diff --git a/packages/CarSystemUI/res/drawable/notification_handle_bar.xml b/packages/CarSystemUI/res/drawable/notification_handle_bar.xml
new file mode 100644
index 000000000000..5ed7499952ed
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/notification_handle_bar.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<ripple
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@android:color/white">
+ <item>
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/clear_all_button_radius"/>
+ <solid android:color="@android:color/white"/>
+ </shape>
+ </item>
+</ripple> \ No newline at end of file
diff --git a/packages/CarSystemUI/res/layout/car_ongoing_privacy_chip.xml b/packages/CarSystemUI/res/layout/car_ongoing_privacy_chip.xml
new file mode 100644
index 000000000000..918abd962dc2
--- /dev/null
+++ b/packages/CarSystemUI/res/layout/car_ongoing_privacy_chip.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<com.android.systemui.statusbar.car.privacy.OngoingPrivacyChip
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/car_privacy_chip"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_margin="@dimen/ongoing_appops_chip_margin"
+ android:layout_toStartOf="@+id/clock_container"
+ android:focusable="true"
+ android:gravity="center_vertical|end"
+ android:orientation="horizontal"
+ android:paddingEnd="@dimen/ongoing_appops_chip_side_padding"
+ android:paddingStart="@dimen/ongoing_appops_chip_side_padding"
+ android:visibility="visible">
+
+ <LinearLayout
+ android:id="@+id/icons_container"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical|start"/>
+</com.android.systemui.statusbar.car.privacy.OngoingPrivacyChip> \ No newline at end of file
diff --git a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
index 925ccb4a162a..cae89c16a03e 100644
--- a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
+++ b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
@@ -65,6 +65,8 @@
/>
</FrameLayout>
+ <include layout="@layout/car_ongoing_privacy_chip"/>
+
<FrameLayout
android:id="@+id/clock_container"
android:layout_width="wrap_content"
diff --git a/packages/CarSystemUI/res/layout/notification_center_activity.xml b/packages/CarSystemUI/res/layout/notification_center_activity.xml
index 5c915b874dde..55b0d875de41 100644
--- a/packages/CarSystemUI/res/layout/notification_center_activity.xml
+++ b/packages/CarSystemUI/res/layout/notification_center_activity.xml
@@ -23,24 +23,27 @@
android:background="@color/notification_shade_background_color">
<View
- android:id="@+id/glass_pane"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- android:translationZ="2dp"
- />
+ android:id="@+id/glass_pane"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:translationZ="2dp"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/notifications"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="vertical"
- app:layout_constraintTop_toTopOf="parent"
+ android:paddingStart="@dimen/notification_shade_list_padding_bottom"
app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toEndOf="parent"/>
+ app:layout_constraintTop_toTopOf="parent"/>
+
+ <include layout="@layout/notification_handle_bar"/>
</com.android.car.notification.CarNotificationView>
diff --git a/packages/CarSystemUI/res/layout/notification_handle_bar.xml b/packages/CarSystemUI/res/layout/notification_handle_bar.xml
new file mode 100644
index 000000000000..99c3a02091db
--- /dev/null
+++ b/packages/CarSystemUI/res/layout/notification_handle_bar.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <View
+ android:id="@+id/handle_bar"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/notification_shade_handle_bar_height"
+ android:layout_marginBottom="@dimen/notification_shade_handle_bar_margin_bottom"
+ android:layout_marginEnd="@dimen/notification_shade_handle_bar_margin_start"
+ android:layout_marginStart="@dimen/notification_shade_handle_bar_margin_end"
+ android:layout_marginTop="@dimen/notification_shade_handle_bar_margin_top"
+ android:background="@drawable/notification_handle_bar"/>
+</merge> \ No newline at end of file
diff --git a/packages/CarSystemUI/res/values/colors.xml b/packages/CarSystemUI/res/values/colors.xml
index 83ec3514c01a..0d69fbba5b63 100644
--- a/packages/CarSystemUI/res/values/colors.xml
+++ b/packages/CarSystemUI/res/values/colors.xml
@@ -34,7 +34,7 @@
<drawable name="system_bar_background">@color/status_bar_background_color</drawable>
<!-- The background color of the notification shade -->
- <color name="notification_shade_background_color">#99000000</color>
+ <color name="notification_shade_background_color">#DD000000</color>
<!-- The color of the dividing line between grouped notifications. -->
<color name="notification_divider_color">@*android:color/notification_action_list</color>
diff --git a/packages/CarSystemUI/res/values/dimens.xml b/packages/CarSystemUI/res/values/dimens.xml
index 8789c8a924b3..7027ce37f670 100644
--- a/packages/CarSystemUI/res/values/dimens.xml
+++ b/packages/CarSystemUI/res/values/dimens.xml
@@ -59,6 +59,16 @@
<dimen name="car_keyline_1">24dp</dimen>
<dimen name="car_keyline_2">96dp</dimen>
<dimen name="car_keyline_3">128dp</dimen>
+ <dimen name="privacy_chip_icon_height">36dp</dimen>
+ <dimen name="privacy_chip_icon_padding_left">0dp</dimen>
+ <dimen name="privacy_chip_icon_padding_right">0dp</dimen>
+ <dimen name="privacy_chip_icon_padding_top">0dp</dimen>
+ <dimen name="privacy_chip_icon_padding_bottom">0dp</dimen>
+
+ <dimen name="privacy_chip_text_padding_left">0dp</dimen>
+ <dimen name="privacy_chip_text_padding_right">0dp</dimen>
+ <dimen name="privacy_chip_text_padding_top">0dp</dimen>
+ <dimen name="privacy_chip_text_padding_bottom">0dp</dimen>
<dimen name="privacy_chip_icon_max_height">100dp</dimen>
@@ -76,6 +86,16 @@
<dimen name="ongoing_appops_chip_bg_padding">4dp</dimen>
<!-- Radius of Ongoing App Ops chip corners -->
<dimen name="ongoing_appops_chip_bg_corner_radius">12dp</dimen>
+ <!-- Start padding for the app icon displayed in the dialog -->
+ <dimen name="privacy_dialog_app_icon_padding_start">40dp</dimen>
+ <!-- End padding for the app opps icon displayed in the dialog -->
+ <dimen name="privacy_dialog_app_ops_icon_padding_end">40dp</dimen>
+ <!-- Top padding for the list of application displayed in the dialog -->
+ <dimen name="privacy_dialog_app_list_padding_top">20dp</dimen>
+ <!-- Top padding for the dialog container-->
+ <dimen name="privacy_dialog_container_padding_top">10dp</dimen>
+ <!-- Top padding for the dialog title-->
+ <dimen name="privacy_dialog_title_padding_start">10dp</dimen>
<!-- Car volume dimens. -->
<dimen name="car_volume_item_height">@*android:dimen/car_single_line_list_item_height</dimen>
@@ -88,4 +108,14 @@
<dimen name="car_volume_item_divider_width">1dp</dimen>
<dimen name="car_volume_item_divider_margin_end">@*android:dimen/car_padding_4</dimen>
<dimen name="car_volume_item_corner_radius">@*android:dimen/car_radius_3</dimen>
+
+ <!-- Car notification shade-->
+ <dimen name="notification_shade_handle_bar_height">10dp</dimen>
+ <dimen name="notification_shade_handle_bar_radius">20dp</dimen>
+ <dimen name="notification_shade_handle_bar_margin_start">500dp</dimen>
+ <dimen name="notification_shade_handle_bar_margin_end">500dp</dimen>
+ <dimen name="notification_shade_handle_bar_margin_top">20dp</dimen>
+ <dimen name="notification_shade_handle_bar_margin_bottom">10dp</dimen>
+ <dimen name="notification_shade_list_padding_bottom">0dp</dimen>
+
</resources>
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 9b6ab06c4708..54e468eed75d 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -131,6 +131,8 @@ public class CarStatusBar extends StatusBar implements
// The container for the notifications.
private CarNotificationView mNotificationView;
private RecyclerView mNotificationList;
+ // The handler bar view at the bottom of notification shade.
+ private View mHandleBar;
// The controller for the notification view.
private NotificationViewController mNotificationViewController;
// The state of if the notification list is currently showing the bottom.
@@ -464,6 +466,7 @@ public class CarStatusBar extends StatusBar implements
mNotificationView = mStatusBarWindow.findViewById(R.id.notification_view);
View glassPane = mStatusBarWindow.findViewById(R.id.glass_pane);
+ mHandleBar = mStatusBarWindow.findViewById(R.id.handle_bar);
mNotificationView.setClickHandlerFactory(mNotificationClickHandlerFactory);
mNotificationView.setNotificationDataManager(mNotificationDataManager);
@@ -521,7 +524,7 @@ public class CarStatusBar extends StatusBar implements
boolean handled = closeGestureDetector.onTouchEvent(event);
boolean isTracking = mIsTracking;
- Rect rect = mNotificationList.getClipBounds();
+ Rect rect = mNotificationView.getClipBounds();
float clippedHeight = 0;
if (rect != null) {
clippedHeight = rect.bottom;
@@ -609,7 +612,7 @@ public class CarStatusBar extends StatusBar implements
to = mNotificationView.getHeight();
}
- Rect rect = mNotificationList.getClipBounds();
+ Rect rect = mNotificationView.getClipBounds();
if (rect != null) {
float from = rect.bottom;
animate(from, to, velocity, isClosing);
@@ -653,7 +656,7 @@ public class CarStatusBar extends StatusBar implements
if (isClosing) {
mStatusBarWindowController.setPanelVisible(false);
mNotificationView.setVisibility(View.INVISIBLE);
- mNotificationList.setClipBounds(null);
+ mNotificationView.setClipBounds(null);
mNotificationViewController.setIsInForeground(false);
// let the status bar know that the panel is closed
setPanelExpanded(false);
@@ -1012,8 +1015,12 @@ public class CarStatusBar extends StatusBar implements
Rect clipBounds = new Rect();
clipBounds.set(0, 0, mNotificationView.getWidth(), height);
// Sets the clip region on the notification list view.
- mNotificationList.setClipBounds(clipBounds);
-
+ mNotificationView.setClipBounds(clipBounds);
+ if (mHandleBar != null) {
+ ViewGroup.MarginLayoutParams lp =
+ (ViewGroup.MarginLayoutParams) mHandleBar.getLayoutParams();
+ mHandleBar.setTranslationY(height - mHandleBar.getHeight() - lp.bottomMargin);
+ }
if (mNotificationView.getHeight() > 0) {
// Calculates the alpha value for the background based on how much of the notification
// shade is visible to the user. When the notification shade is completely open then
@@ -1095,9 +1102,6 @@ public class CarStatusBar extends StatusBar implements
@Override
public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX,
float distanceY) {
- if (!mNotificationListAtBottomAtTimeOfTouch && !mNotificationListAtBottom) {
- return false;
- }
// should not clip while scroll to the bottom of the list.
if (!mNotificationListAtBottomAtTimeOfTouch) {
return false;
@@ -1134,7 +1138,8 @@ public class CarStatusBar extends StatusBar implements
@Override
public boolean onFling(MotionEvent event1, MotionEvent event2,
float velocityX, float velocityY) {
- if (!mNotificationListAtBottomAtTimeOfTouch && !mNotificationListAtBottom) {
+ // should not fling if the touch does not start when view is at the bottom of the list.
+ if (!mNotificationListAtBottomAtTimeOfTouch) {
return false;
}
if (Math.abs(event1.getX() - event2.getX()) > SWIPE_MAX_OFF_PATH
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java
new file mode 100644
index 000000000000..ead1de2bd352
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.car.privacy;
+
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.appops.AppOpItem;
+import com.android.systemui.appops.AppOpsController;
+import com.android.systemui.plugins.ActivityStarter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * Layout defining the privacy chip that will be displayed in CarStatusRar with the information for
+ * which applications are using AppOpps permission fpr camera, mic and location.
+ */
+public class OngoingPrivacyChip extends LinearLayout implements View.OnClickListener {
+
+ private Context mContext;
+
+ private LinearLayout mIconsContainer;
+ private List<PrivacyItem> mPrivacyItems;
+ private static AppOpsController sAppOpsController;
+ private UserManager mUserManager;
+ private int mCurrentUser;
+ private List<Integer> mCurrentUserIds;
+ private boolean mListening = false;
+ PrivacyDialogBuilder mPrivacyDialogBuilder;
+ private LinearLayout mPrivacyChip;
+ private ActivityStarter mActivityStarter;
+
+ protected static final int[] OPS = new int[]{
+ AppOpsManager.OP_CAMERA,
+ AppOpsManager.OP_RECORD_AUDIO,
+ AppOpsManager.OP_COARSE_LOCATION,
+ AppOpsManager.OP_FINE_LOCATION
+ };
+
+ public OngoingPrivacyChip(Context context) {
+ super(context, null);
+ init(context);
+ }
+
+ public OngoingPrivacyChip(Context context, AttributeSet attr) {
+ super(context, attr);
+ init(context);
+ }
+
+ public OngoingPrivacyChip(Context context, AttributeSet attr, int defStyle) {
+ super(context, attr, defStyle);
+ init(context);
+ }
+
+ public OngoingPrivacyChip(Context context, AttributeSet attr, int defStyle, int a) {
+ super(context, attr, defStyle, a);
+ init(context);
+ }
+
+ private void init(Context context) {
+ mContext = context;
+ mPrivacyItems = new ArrayList<>();
+ sAppOpsController = Dependency.get(AppOpsController.class);
+ mUserManager = mContext.getSystemService(UserManager.class);
+ mActivityStarter = Dependency.get(ActivityStarter.class);
+ mCurrentUser = ActivityManager.getCurrentUser();
+ mCurrentUserIds = mUserManager.getProfiles(mCurrentUser).stream().map(
+ userInfo -> userInfo.id).collect(Collectors.toList());
+
+ mPrivacyDialogBuilder = new PrivacyDialogBuilder(context, mPrivacyItems);
+ }
+
+ private AppOpsController.Callback mCallback = new AppOpsController.Callback() {
+
+ @Override
+ public void onActiveStateChanged(int code, int uid, String packageName, boolean active) {
+ int userId = UserHandle.getUserId(uid);
+ if (mCurrentUserIds.contains(userId)) {
+ updatePrivacyList();
+ }
+ }
+ };
+
+ @Override
+ public void onFinishInflate() {
+ mIconsContainer = findViewById(R.id.icons_container);
+ mPrivacyChip = (LinearLayout) findViewById(R.id.car_privacy_chip);
+ if (mPrivacyChip != null) {
+ mPrivacyChip.setOnClickListener(this);
+ setListening(true);
+ }
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ if (mPrivacyChip != null) {
+ setListening(false);
+ }
+ super.onDetachedFromWindow();
+ }
+
+ @Override
+ public void onClick(View v) {
+ updatePrivacyList();
+ Handler mUiHandler = new Handler(Looper.getMainLooper());
+ mUiHandler.post(() -> {
+ mActivityStarter.postStartActivityDismissingKeyguard(
+ new Intent(Intent.ACTION_REVIEW_ONGOING_PERMISSION_USAGE), 0);
+ });
+ }
+
+ private void setListening(boolean listen) {
+ if (mListening == listen) {
+ return;
+ }
+ mListening = listen;
+ if (mListening) {
+ sAppOpsController.addCallback(OPS, mCallback);
+ updatePrivacyList();
+ } else {
+ sAppOpsController.removeCallback(OPS, mCallback);
+ }
+ }
+
+ private void updatePrivacyList() {
+ mPrivacyItems = mCurrentUserIds.stream()
+ .flatMap(item -> sAppOpsController.getActiveAppOpsForUser(item).stream())
+ .filter(Objects::nonNull)
+ .map(item -> toPrivacyItem(item))
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ mPrivacyDialogBuilder = new PrivacyDialogBuilder(mContext, mPrivacyItems);
+
+ Handler refresh = new Handler(Looper.getMainLooper());
+ refresh.post(new Runnable() {
+ @Override
+ public void run() {
+ updateView();
+ }
+ });
+ }
+
+ private PrivacyItem toPrivacyItem(AppOpItem appOpItem) {
+ PrivacyType type;
+ switch (appOpItem.getCode()) {
+ case AppOpsManager.OP_CAMERA:
+ type = PrivacyType.TYPE_CAMERA;
+ break;
+ case AppOpsManager.OP_COARSE_LOCATION:
+ type = PrivacyType.TYPE_LOCATION;
+ break;
+ case AppOpsManager.OP_FINE_LOCATION:
+ type = PrivacyType.TYPE_LOCATION;
+ break;
+ case AppOpsManager.OP_RECORD_AUDIO:
+ type = PrivacyType.TYPE_MICROPHONE;
+ break;
+ default:
+ return null;
+ }
+ PrivacyApplication app = new PrivacyApplication(appOpItem.getPackageName(), mContext);
+ return new PrivacyItem(type, app, appOpItem.getTimeStarted());
+ }
+
+ // Should only be called if the mPrivacyDialogBuilder icons or app changed
+ private void updateView() {
+ if (mPrivacyItems.isEmpty()) {
+ mPrivacyChip.setVisibility(GONE);
+ return;
+ }
+ mPrivacyChip.setVisibility(VISIBLE);
+ setIcons(mPrivacyDialogBuilder);
+
+ requestLayout();
+ }
+
+ private void setIcons(PrivacyDialogBuilder dialogBuilder) {
+ mIconsContainer.removeAllViews();
+ dialogBuilder.generateIcons().forEach(item -> {
+ int size = mContext.getResources().getDimensionPixelSize(
+ R.dimen.privacy_chip_icon_height);
+ ImageView image = new ImageView(mContext);
+ image.setImageDrawable(item);
+ LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(size, size);
+
+ int leftPadding = mContext.getResources().getDimensionPixelSize(
+ R.dimen.privacy_chip_icon_padding_left);
+ int topPadding = mContext.getResources().getDimensionPixelSize(
+ R.dimen.privacy_chip_icon_padding_top);
+ int rightPadding = mContext.getResources().getDimensionPixelSize(
+ R.dimen.privacy_chip_icon_padding_right);
+ int bottomPadding = mContext.getResources().getDimensionPixelSize(
+ R.dimen.privacy_chip_icon_padding_bottom);
+ image.setLayoutParams(layoutParams);
+ image.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
+ mIconsContainer.addView(image);
+ });
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java
new file mode 100644
index 000000000000..5ec7a77cb305
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.car.privacy;
+
+import android.car.userlib.CarUserManagerHelper;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+
+/**
+ * Class to hold the data for the applications that are using the AppOps permissions.
+ */
+public class PrivacyApplication {
+ private static final String TAG = "PrivacyApplication";
+
+ private Drawable mIcon;
+ private String mApplicationName;
+
+ public PrivacyApplication(String packageName, Context context) {
+ try {
+ CarUserManagerHelper carUserManagerHelper = new CarUserManagerHelper(context);
+ ApplicationInfo app = context.getPackageManager()
+ .getApplicationInfoAsUser(packageName, 0,
+ carUserManagerHelper.getCurrentForegroundUserId());
+ mIcon = context.getPackageManager().getApplicationIcon(app);
+ mApplicationName = context.getPackageManager().getApplicationLabel(app).toString();
+ } catch (PackageManager.NameNotFoundException e) {
+ mApplicationName = packageName;
+ Log.e(TAG, "Failed to to find package name", e);
+ }
+ }
+
+ /**
+ * Gets the application name.
+ */
+ public Drawable getIcon() {
+ return mIcon;
+ }
+
+ /**
+ * Gets the application name.
+ */
+ public String getApplicationName() {
+ return mApplicationName;
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyDialogBuilder.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyDialogBuilder.java
new file mode 100644
index 000000000000..3b83e7cc0623
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyDialogBuilder.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.car.privacy;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * Helper class to build the {@link OngoingPrivacyDialog}
+ */
+public class PrivacyDialogBuilder {
+
+ private Map<PrivacyType, List<PrivacyItem>> mItemsByType;
+ private PrivacyApplication mApplication;
+ private Context mContext;
+
+ public PrivacyDialogBuilder(Context context, List<PrivacyItem> itemsList) {
+ mContext = context;
+ mItemsByType = itemsList.stream().filter(Objects::nonNull).collect(
+ Collectors.groupingBy(PrivacyItem::getPrivacyType));
+ List<PrivacyApplication> apps = itemsList.stream().filter(Objects::nonNull).map(
+ PrivacyItem::getPrivacyApplication).distinct().collect(Collectors.toList());
+ mApplication = apps.size() == 1 ? apps.get(0) : null;
+ }
+
+ /**
+ * Gets the icon id for all the {@link PrivacyItem} in the same order as of itemList.
+ */
+ public List<Drawable> generateIcons() {
+ return mItemsByType.keySet().stream().map(item -> item.getIconId(mContext)).collect(
+ Collectors.toList());
+ }
+
+ /**
+ * Gets the application object.
+ */
+ public PrivacyApplication getApplication() {
+ return mApplication;
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java
new file mode 100644
index 000000000000..fca137392d74
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.car.privacy;
+
+/**
+ * Class for holding the data of each privacy item displayed in {@link OngoingPrivacyDialog}
+ */
+public class PrivacyItem {
+
+ private PrivacyType mPrivacyType;
+ private PrivacyApplication mPrivacyApplication;
+
+ public PrivacyItem(PrivacyType privacyType, PrivacyApplication privacyApplication,
+ long timeStarted) {
+ this.mPrivacyType = privacyType;
+ this.mPrivacyApplication = privacyApplication;
+ }
+
+ /**
+ * Gets the application object.
+ */
+ public PrivacyApplication getPrivacyApplication() {
+ return mPrivacyApplication;
+ }
+
+ /**
+ * Gets the privacy type for the application.
+ */
+ public PrivacyType getPrivacyType() {
+ return mPrivacyType;
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyType.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyType.java
new file mode 100644
index 000000000000..8955c87bbff4
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyType.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.car.privacy;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+
+import com.android.systemui.R;
+
+/**
+ * Enum for storing data for camera, mic and location.
+ */
+public enum PrivacyType {
+ TYPE_CAMERA(R.string.privacy_type_camera, com.android.internal.R.drawable.ic_camera),
+ TYPE_LOCATION(R.string.privacy_type_location, R.drawable.stat_sys_location),
+ TYPE_MICROPHONE(R.string.privacy_type_microphone, R.drawable.ic_mic_white);
+
+ private int mNameId;
+ private int mIconId;
+
+ PrivacyType(int nameId, int iconId) {
+ mNameId = nameId;
+ mIconId = iconId;
+ }
+
+ /**
+ * Get the icon Id.
+ */
+ public Drawable getIconId(Context context) {
+ return context.getResources().getDrawable(mIconId, null);
+ }
+
+ /**
+ * Get the name Id.
+ */
+ public String getNameId(Context context) {
+ return context.getResources().getString(mNameId);
+ }
+}
diff --git a/packages/CtsShim/apk/arm/CtsShim.apk b/packages/CtsShim/apk/arm/CtsShim.apk
index a91160368cb8..7d9f8e3fe21e 100644
--- a/packages/CtsShim/apk/arm/CtsShim.apk
+++ b/packages/CtsShim/apk/arm/CtsShim.apk
Binary files differ
diff --git a/packages/CtsShim/apk/arm/CtsShimPriv.apk b/packages/CtsShim/apk/arm/CtsShimPriv.apk
index 845d781f38f3..dcccada3c8a3 100644
--- a/packages/CtsShim/apk/arm/CtsShimPriv.apk
+++ b/packages/CtsShim/apk/arm/CtsShimPriv.apk
Binary files differ
diff --git a/packages/CtsShim/apk/x86/CtsShim.apk b/packages/CtsShim/apk/x86/CtsShim.apk
index a91160368cb8..7d9f8e3fe21e 100644
--- a/packages/CtsShim/apk/x86/CtsShim.apk
+++ b/packages/CtsShim/apk/x86/CtsShim.apk
Binary files differ
diff --git a/packages/CtsShim/apk/x86/CtsShimPriv.apk b/packages/CtsShim/apk/x86/CtsShimPriv.apk
index 2fc9a94037fa..3501fa424123 100644
--- a/packages/CtsShim/apk/x86/CtsShimPriv.apk
+++ b/packages/CtsShim/apk/x86/CtsShimPriv.apk
Binary files differ
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/BootCompletedReceiver.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/BootCompletedReceiver.java
index ea7b378eb607..06c52942e671 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/BootCompletedReceiver.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/BootCompletedReceiver.java
@@ -22,8 +22,8 @@ import android.content.Intent;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.image.DynamicSystemClient;
+import android.os.image.DynamicSystemManager;
import android.util.FeatureFlagUtils;
-import android.util.Log;
/**
@@ -37,21 +37,26 @@ public class BootCompletedReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- if (!featureFlagEnabled()) {
+ String action = intent.getAction();
+
+ if (!Intent.ACTION_BOOT_COMPLETED.equals(action)) {
return;
}
- String action = intent.getAction();
-
- Log.d(TAG, "Broadcast received: " + action);
+ DynamicSystemManager dynSystem =
+ (DynamicSystemManager) context.getSystemService(Context.DYNAMIC_SYSTEM_SERVICE);
- if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {
- Intent startServiceIntent = new Intent(
- context, DynamicSystemInstallationService.class);
+ boolean isInUse = (dynSystem != null) && dynSystem.isInUse();
- startServiceIntent.setAction(DynamicSystemClient.ACTION_NOTIFY_IF_IN_USE);
- context.startServiceAsUser(startServiceIntent, UserHandle.SYSTEM);
+ if (!isInUse && !featureFlagEnabled()) {
+ return;
}
+
+ Intent startServiceIntent = new Intent(
+ context, DynamicSystemInstallationService.class);
+
+ startServiceIntent.setAction(DynamicSystemClient.ACTION_NOTIFY_IF_IN_USE);
+ context.startServiceAsUser(startServiceIntent, UserHandle.SYSTEM);
}
private boolean featureFlagEnabled() {
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
index b0e28a029436..077f7ecd3e46 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
@@ -37,7 +37,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
private static final String TAG = "InstallationAsyncTask";
- private static final int READ_BUFFER_SIZE = 1 << 19;
+ private static final int READ_BUFFER_SIZE = 1 << 13;
private class InvalidImageUrlException extends RuntimeException {
private InvalidImageUrlException(String message) {
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index 73c789516754..d01878aef37d 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -30,11 +30,9 @@ import android.app.Notification;
import android.app.NotificationChannel;
import android.content.Context;
import android.content.pm.IPackageManager;
-import android.ext.services.notification.AgingHelper.Callback;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.service.notification.Adjustment;
@@ -76,8 +74,6 @@ import java.util.concurrent.Executors;
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 AGE_NOTIFICATIONS = SystemProperties.getBoolean(
- "debug.age_notifs", false);
private static final String TAG_ASSISTANT = "assistant";
private static final String TAG_IMPRESSION = "impression-set";
@@ -94,7 +90,6 @@ public class Assistant extends NotificationAssistantService {
private SmartActionsHelper mSmartActionsHelper;
private NotificationCategorizer mNotificationCategorizer;
- private AgingHelper mAgingHelper;
// key : impressions tracker
// TODO: prune deleted channels and apps
@@ -125,9 +120,6 @@ public class Assistant extends NotificationAssistantService {
getApplicationContext().getContentResolver(), getUserId(), this::updateThresholds);
mSmartActionsHelper = new SmartActionsHelper(getContext(), mSettings);
mNotificationCategorizer = new NotificationCategorizer();
- mAgingHelper = new AgingHelper(getContext(),
- mNotificationCategorizer,
- new AgingCallback());
mSmsHelper = new SmsHelper(this);
mSmsHelper.initialize();
}
@@ -301,15 +293,18 @@ public class Assistant extends NotificationAssistantService {
sbn, ranking.getChannel(), mSmsHelper);
String key = getKey(
sbn.getPackageName(), sbn.getUserId(), ranking.getChannel().getId());
- ChannelImpressions ci = mkeyToImpressions.getOrDefault(key,
- createChannelImpressionsWithThresholds());
- if (ranking.getImportance() > IMPORTANCE_MIN && ci.shouldTriggerBlock()) {
+ boolean shouldTriggerBlock;
+ synchronized (mkeyToImpressions) {
+ ChannelImpressions ci = mkeyToImpressions.getOrDefault(key,
+ createChannelImpressionsWithThresholds());
+ mkeyToImpressions.put(key, ci);
+ shouldTriggerBlock = ci.shouldTriggerBlock();
+ }
+ if (ranking.getImportance() > IMPORTANCE_MIN && shouldTriggerBlock) {
adjustNotification(createNegativeAdjustment(
sbn.getPackageName(), sbn.getKey(), sbn.getUserId()));
}
- mkeyToImpressions.put(key, ci);
mLiveNotifications.put(sbn.getKey(), entry);
- mAgingHelper.onNotificationPosted(entry);
}
} catch (Throwable e) {
Log.e(TAG, "Error occurred processing post", e);
@@ -324,8 +319,6 @@ public class Assistant extends NotificationAssistantService {
return;
}
- mAgingHelper.onNotificationRemoved(sbn.getKey());
-
boolean updatedImpressions = false;
String channelId = mLiveNotifications.remove(sbn.getKey()).getChannel().getId();
String key = getKey(sbn.getPackageName(), sbn.getUserId(), channelId);
@@ -370,22 +363,6 @@ public class Assistant extends NotificationAssistantService {
@Override
public void onNotificationsSeen(List<String> keys) {
- try {
- if (keys == null) {
- return;
- }
-
- for (String key : keys) {
- NotificationEntry entry = mLiveNotifications.get(key);
-
- if (entry != null) {
- entry.setSeen();
- mAgingHelper.onNotificationSeen(entry);
- }
- }
- } catch (Throwable e) {
- Slog.e(TAG, "Error occurred processing seen", e);
- }
}
@Override
@@ -452,9 +429,6 @@ public class Assistant extends NotificationAssistantService {
@Override
public void onListenerDisconnected() {
- if (mAgingHelper != null) {
- mAgingHelper.onDestroy();
- }
}
private boolean isForCurrentUser(StatusBarNotification sbn) {
@@ -537,21 +511,4 @@ public class Assistant extends NotificationAssistantService {
}
}
}
-
- protected final class AgingCallback implements Callback {
- @Override
- public void sendAdjustment(String key, int newImportance) {
- if (AGE_NOTIFICATIONS) {
- NotificationEntry entry = mLiveNotifications.get(key);
- if (entry != null) {
- Bundle bundle = new Bundle();
- bundle.putInt(KEY_IMPORTANCE, newImportance);
- Adjustment adjustment = new Adjustment(entry.getSbn().getPackageName(), key,
- bundle, "aging", entry.getSbn().getUserId());
- adjustNotification(adjustment);
- }
- }
- }
- }
-
}
diff --git a/packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImpl.java b/packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImpl.java
index 765e9f95216d..670b419a8aa3 100644
--- a/packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImpl.java
+++ b/packages/ExtServices/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImpl.java
@@ -39,9 +39,9 @@ public final class ExplicitHealthCheckServiceImpl extends ExplicitHealthCheckSer
// TODO: Add build dependency on NetworkStack stable AIDL so we can stop hard coding class name
private static final String NETWORK_STACK_CONNECTOR_CLASS =
"android.net.INetworkStackConnector";
- private static final String PROPERTY_WATCHDOG_REQUEST_TIMEOUT_MILLIS =
+ public static final String PROPERTY_WATCHDOG_REQUEST_TIMEOUT_MILLIS =
"watchdog_request_timeout_millis";
- private static final long DEFAULT_REQUEST_TIMEOUT_MILLIS =
+ public static final long DEFAULT_REQUEST_TIMEOUT_MILLIS =
TimeUnit.HOURS.toMillis(1);
// Modified only #onCreate, using concurrent collection to ensure thread visibility
private final Map<String, ExplicitHealthChecker> mSupportedCheckers = new ConcurrentHashMap<>();
diff --git a/packages/ExtServices/tests/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImplTest.java b/packages/ExtServices/tests/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImplTest.java
new file mode 100644
index 000000000000..a9cb63e2a200
--- /dev/null
+++ b/packages/ExtServices/tests/src/android/ext/services/watchdog/ExplicitHealthCheckServiceImplTest.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.ext.services.watchdog;
+
+import static android.service.watchdog.ExplicitHealthCheckService.EXTRA_REQUESTED_PACKAGES;
+import static android.service.watchdog.ExplicitHealthCheckService.EXTRA_SUPPORTED_PACKAGES;
+import static android.service.watchdog.ExplicitHealthCheckService.PackageConfig;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
+
+import android.Manifest;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.RemoteCallback;
+import android.service.watchdog.ExplicitHealthCheckService;
+import android.service.watchdog.IExplicitHealthCheckService;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.rule.ServiceTestRule;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Contains the base tests that does not rely on the specific algorithm implementation.
+ */
+public class ExplicitHealthCheckServiceImplTest {
+ private static final String NETWORK_STACK_CONNECTOR_CLASS =
+ "android.net.INetworkStackConnector";
+
+ private final Context mContext = InstrumentationRegistry.getContext();
+ private IExplicitHealthCheckService mService;
+ private String mNetworkStackPackageName;
+
+ @Rule
+ public ServiceTestRule mServiceTestRule;
+
+ @Before
+ public void setUp() throws Exception {
+ InstrumentationRegistry
+ .getInstrumentation()
+ .getUiAutomation()
+ .adoptShellPermissionIdentity(
+ Manifest.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE);
+
+ mServiceTestRule = new ServiceTestRule();
+ mService = IExplicitHealthCheckService.Stub.asInterface(
+ mServiceTestRule.bindService(getExtServiceIntent()));
+ mNetworkStackPackageName = getNetworkStackPackage();
+ assumeFalse(mNetworkStackPackageName == null);
+ }
+
+ @After
+ public void tearDown() {
+ InstrumentationRegistry
+ .getInstrumentation()
+ .getUiAutomation()
+ .dropShellPermissionIdentity();
+ }
+
+ @Test
+ public void testHealthCheckSupportedPackage() throws Exception {
+ List<PackageConfig> supportedPackages = new ArrayList<>();
+ CountDownLatch latch = new CountDownLatch(1);
+
+ mService.getSupportedPackages(new RemoteCallback(result -> {
+ supportedPackages.addAll(result.getParcelableArrayList(EXTRA_SUPPORTED_PACKAGES));
+ latch.countDown();
+ }));
+ latch.await();
+
+ // TODO: Support DeviceConfig changes for the health check timeout
+ assertThat(supportedPackages).hasSize(1);
+ assertThat(supportedPackages.get(0).getPackageName())
+ .isEqualTo(mNetworkStackPackageName);
+ assertThat(supportedPackages.get(0).getHealthCheckTimeoutMillis())
+ .isEqualTo(ExplicitHealthCheckServiceImpl.DEFAULT_REQUEST_TIMEOUT_MILLIS);
+ }
+
+ @Test
+ public void testHealthCheckRequests() throws Exception {
+ List<String> requestedPackages = new ArrayList<>();
+ CountDownLatch latch1 = new CountDownLatch(1);
+ CountDownLatch latch2 = new CountDownLatch(1);
+ CountDownLatch latch3 = new CountDownLatch(1);
+
+ // Initially, no health checks requested
+ mService.getRequestedPackages(new RemoteCallback(result -> {
+ requestedPackages.addAll(result.getParcelableArrayList(EXTRA_REQUESTED_PACKAGES));
+ latch1.countDown();
+ }));
+
+ // Verify that no health checks requested
+ latch1.await();
+ assertThat(requestedPackages).isEmpty();
+
+ // Then request health check
+ mService.request(mNetworkStackPackageName);
+
+ // Verify that health check is requested for network stack
+ mService.getRequestedPackages(new RemoteCallback(result -> {
+ requestedPackages.addAll(result.getParcelableArrayList(EXTRA_REQUESTED_PACKAGES));
+ latch2.countDown();
+ }));
+ latch2.await();
+ assertThat(requestedPackages).hasSize(1);
+ assertThat(requestedPackages.get(0)).isEqualTo(mNetworkStackPackageName);
+
+ // Then cancel health check
+ requestedPackages.clear();
+ mService.cancel(mNetworkStackPackageName);
+
+ // Verify that health check is cancelled for network stack
+ mService.getRequestedPackages(new RemoteCallback(result -> {
+ requestedPackages.addAll(result.getParcelableArrayList(EXTRA_REQUESTED_PACKAGES));
+ latch3.countDown();
+ }));
+ latch3.await();
+ assertThat(requestedPackages).isEmpty();
+ }
+
+ private String getNetworkStackPackage() {
+ Intent intent = new Intent(NETWORK_STACK_CONNECTOR_CLASS);
+ ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
+ if (comp != null) {
+ return comp.getPackageName();
+ } else {
+ // On Go devices, or any device that does not ship the network stack module.
+ // The network stack will live in system_server process, so no need to monitor.
+ return null;
+ }
+ }
+
+ private Intent getExtServiceIntent() {
+ ComponentName component = getExtServiceComponentNameLocked();
+ if (component == null) {
+ fail("Health check service not found");
+ }
+ Intent intent = new Intent();
+ intent.setComponent(component);
+ return intent;
+ }
+
+ private ComponentName getExtServiceComponentNameLocked() {
+ ServiceInfo serviceInfo = getExtServiceInfoLocked();
+ if (serviceInfo == null) {
+ return null;
+ }
+
+ final ComponentName name = new ComponentName(serviceInfo.packageName, serviceInfo.name);
+ if (!Manifest.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE
+ .equals(serviceInfo.permission)) {
+ return null;
+ }
+ return name;
+ }
+
+ private ServiceInfo getExtServiceInfoLocked() {
+ final String packageName =
+ mContext.getPackageManager().getServicesSystemSharedLibraryPackageName();
+ if (packageName == null) {
+ return null;
+ }
+
+ final Intent intent = new Intent(ExplicitHealthCheckService.SERVICE_INTERFACE);
+ intent.setPackage(packageName);
+ final ResolveInfo resolveInfo = mContext.getPackageManager().resolveService(intent,
+ PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+ if (resolveInfo == null || resolveInfo.serviceInfo == null) {
+ return null;
+ }
+ return resolveInfo.serviceInfo;
+ }
+}
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index e15526a571f5..c013b8c09ed6 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -42,8 +42,8 @@ android_library {
static_libs: [
"androidx.annotation_annotation",
"ipmemorystore-client",
- "netd_aidl_interface-java",
- "networkstack-aidl-interfaces-java",
+ "netd_aidl_interface-V2-java",
+ "networkstack-aidl-interfaces-V3-java",
"datastallprotosnano",
"networkstackprotosnano",
"captiveportal-lib",
@@ -109,7 +109,9 @@ android_app {
// InProcessNetworkStack is a replacement for NetworkStack
overrides: ["NetworkStack"],
// The permission configuration *must* be included to ensure security of the device
- required: ["PlatformNetworkPermissionConfig"],
+ // The InProcessNetworkStack goes together with the PlatformCaptivePortalLogin, which replaces
+ // the default CaptivePortalLogin.
+ required: ["PlatformNetworkPermissionConfig", "PlatformCaptivePortalLogin"],
}
// Updatable network stack packaged as an application
diff --git a/packages/NetworkStack/src/com/android/server/NetworkStackService.java b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
index c394d4c4cfd3..2fae0c703084 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkStackService.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
@@ -49,6 +49,7 @@ import android.net.shared.PrivateDnsConfig;
import android.net.util.SharedLog;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.ArraySet;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
@@ -62,7 +63,6 @@ import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.concurrent.atomic.AtomicInteger;
/**
* Android service used to start the network stack when bound to via an intent.
@@ -118,14 +118,12 @@ public class NetworkStackService extends Service {
@GuardedBy("mValidationLogs")
private final ArrayDeque<SharedLog> mValidationLogs = new ArrayDeque<>(MAX_VALIDATION_LOGS);
- private static final int VERSION_UNKNOWN = 0;
private static final String DUMPSYS_ARG_VERSION = "version";
- /** Version of the AIDL interfaces observed on the system */
- private final AtomicInteger mSystemAidlVersion = new AtomicInteger(VERSION_UNKNOWN);
-
- /** Whether different versions have been observed on interfaces provided by the system */
- private volatile boolean mConflictingSystemAidlVersions = false;
+ /** Version of the framework AIDL interfaces observed. Should hold only one value. */
+ @GuardedBy("mFrameworkAidlVersions")
+ private final ArraySet<Integer> mFrameworkAidlVersions = new ArraySet<>(1);
+ private final int mNetdAidlVersion;
private SharedLog addValidationLogs(Network network, String name) {
final SharedLog log = new SharedLog(NUM_VALIDATION_LOG_LINES, network + " - " + name);
@@ -146,6 +144,15 @@ public class NetworkStackService extends Service {
mCm = context.getSystemService(ConnectivityManager.class);
mIpMemoryStoreService = new IpMemoryStoreService(context);
+ int netdVersion;
+ try {
+ netdVersion = mNetd.getInterfaceVersion();
+ } catch (RemoteException e) {
+ mLog.e("Error obtaining INetd version", e);
+ netdVersion = -1;
+ }
+ mNetdAidlVersion = netdVersion;
+
try {
mObserverRegistry.register(mNetd);
} catch (RemoteException e) {
@@ -154,9 +161,8 @@ public class NetworkStackService extends Service {
}
private void updateSystemAidlVersion(final int version) {
- final int previousVersion = mSystemAidlVersion.getAndSet(version);
- if (previousVersion != VERSION_UNKNOWN && previousVersion != version) {
- mConflictingSystemAidlVersions = true;
+ synchronized (mFrameworkAidlVersions) {
+ mFrameworkAidlVersions.add(version);
}
}
@@ -230,12 +236,16 @@ public class NetworkStackService extends Service {
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
@Nullable String[] args) {
checkDumpPermission();
+
+ final IndentingPrintWriter pw = new IndentingPrintWriter(fout, " ");
+ pw.println("NetworkStack version:");
+ dumpVersion(pw);
+ pw.println();
+
if (args != null && args.length >= 1 && DUMPSYS_ARG_VERSION.equals(args[0])) {
- dumpVersion(fout);
return;
}
- final IndentingPrintWriter pw = new IndentingPrintWriter(fout, " ");
pw.println("NetworkStack logs:");
mLog.dump(fd, pw, args);
@@ -283,8 +293,10 @@ public class NetworkStackService extends Service {
*/
private void dumpVersion(@NonNull PrintWriter fout) {
fout.println("NetworkStackConnector: " + this.VERSION);
- fout.println("SystemServer: " + mSystemAidlVersion);
- fout.println("SystemServerConflicts: " + mConflictingSystemAidlVersions);
+ synchronized (mFrameworkAidlVersions) {
+ fout.println("SystemServer: " + mFrameworkAidlVersions);
+ }
+ fout.println("Netd: " + mNetdAidlVersion);
}
@Override
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java
index 6a6bf83bd3c8..8312dfeb1a3b 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java
@@ -410,6 +410,10 @@ public class IpMemoryStoreService extends IIpMemoryStore.Stub {
});
}
+ @Override
+ public void factoryReset() {
+ }
+
/** Get db size threshold. */
@VisibleForTesting
protected int getDbSizeThreshold() {
diff --git a/packages/NetworkStack/tests/Android.bp b/packages/NetworkStack/tests/unit/Android.bp
index 039f6bf791fb..6cc80543fc74 100644
--- a/packages/NetworkStack/tests/Android.bp
+++ b/packages/NetworkStack/tests/unit/Android.bp
@@ -72,7 +72,7 @@ android_test {
"libutilscallstack",
"libziparchive",
"libz",
- "netd_aidl_interface-cpp",
+ "netd_aidl_interface-V2-cpp",
],
}
@@ -94,7 +94,7 @@ cc_library_shared {
"liblog",
"libcutils",
"libnativehelper",
- "netd_aidl_interface-cpp",
+ "netd_aidl_interface-V2-cpp",
],
static_libs: [
"libapf",
diff --git a/packages/NetworkStack/tests/AndroidManifest.xml b/packages/NetworkStack/tests/unit/AndroidManifest.xml
index 5dcf6ff1b514..5dcf6ff1b514 100644
--- a/packages/NetworkStack/tests/AndroidManifest.xml
+++ b/packages/NetworkStack/tests/unit/AndroidManifest.xml
diff --git a/packages/NetworkStack/tests/AndroidTest.xml b/packages/NetworkStack/tests/unit/AndroidTest.xml
index 047bc2e67808..047bc2e67808 100644
--- a/packages/NetworkStack/tests/AndroidTest.xml
+++ b/packages/NetworkStack/tests/unit/AndroidTest.xml
diff --git a/packages/NetworkStack/tests/jni/apf_jni.cpp b/packages/NetworkStack/tests/unit/jni/apf_jni.cpp
index 4222adf9e06b..4222adf9e06b 100644
--- a/packages/NetworkStack/tests/jni/apf_jni.cpp
+++ b/packages/NetworkStack/tests/unit/jni/apf_jni.cpp
diff --git a/packages/NetworkStack/tests/res/raw/apf.pcap b/packages/NetworkStack/tests/unit/res/raw/apf.pcap
index 963165f19f73..963165f19f73 100644
--- a/packages/NetworkStack/tests/res/raw/apf.pcap
+++ b/packages/NetworkStack/tests/unit/res/raw/apf.pcap
Binary files differ
diff --git a/packages/NetworkStack/tests/res/raw/apfPcap.pcap b/packages/NetworkStack/tests/unit/res/raw/apfPcap.pcap
index 6f69c4add0f8..6f69c4add0f8 100644
--- a/packages/NetworkStack/tests/res/raw/apfPcap.pcap
+++ b/packages/NetworkStack/tests/unit/res/raw/apfPcap.pcap
Binary files differ
diff --git a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java b/packages/NetworkStack/tests/unit/src/android/net/apf/ApfTest.java
index 8f2b96807860..8f2b96807860 100644
--- a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
+++ b/packages/NetworkStack/tests/unit/src/android/net/apf/ApfTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/apf/Bpf2Apf.java b/packages/NetworkStack/tests/unit/src/android/net/apf/Bpf2Apf.java
index 5d57cde22fb1..5d57cde22fb1 100644
--- a/packages/NetworkStack/tests/src/android/net/apf/Bpf2Apf.java
+++ b/packages/NetworkStack/tests/unit/src/android/net/apf/Bpf2Apf.java
diff --git a/packages/NetworkStack/tests/src/android/net/captiveportal/CaptivePortalProbeSpecTest.java b/packages/NetworkStack/tests/unit/src/android/net/captiveportal/CaptivePortalProbeSpecTest.java
index f948086ac79b..f948086ac79b 100644
--- a/packages/NetworkStack/tests/src/android/net/captiveportal/CaptivePortalProbeSpecTest.java
+++ b/packages/NetworkStack/tests/unit/src/android/net/captiveportal/CaptivePortalProbeSpecTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpLeaseRepositoryTest.java b/packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpLeaseRepositoryTest.java
index 27d725540d34..27d725540d34 100644
--- a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpLeaseRepositoryTest.java
+++ b/packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpLeaseRepositoryTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java b/packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpPacketTest.java
index a30d3e492406..a30d3e492406 100644
--- a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpPacketTest.java
+++ b/packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpPacketTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java b/packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpServerTest.java
index f0e2f1b8d459..f0e2f1b8d459 100644
--- a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java
+++ b/packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpServerTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServingParamsTest.java b/packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpServingParamsTest.java
index 57a87a4d3fb1..57a87a4d3fb1 100644
--- a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServingParamsTest.java
+++ b/packages/NetworkStack/tests/unit/src/android/net/dhcp/DhcpServingParamsTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java b/packages/NetworkStack/tests/unit/src/android/net/ip/IpClientTest.java
index 5f8000634ffa..5f8000634ffa 100644
--- a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
+++ b/packages/NetworkStack/tests/unit/src/android/net/ip/IpClientTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/ip/IpReachabilityMonitorTest.java b/packages/NetworkStack/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.java
index 64b168ae2b5a..64b168ae2b5a 100644
--- a/packages/NetworkStack/tests/src/android/net/ip/IpReachabilityMonitorTest.java
+++ b/packages/NetworkStack/tests/unit/src/android/net/ip/IpReachabilityMonitorTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/util/ConnectivityPacketSummaryTest.java b/packages/NetworkStack/tests/unit/src/android/net/util/ConnectivityPacketSummaryTest.java
index 71be8b38d3fe..71be8b38d3fe 100644
--- a/packages/NetworkStack/tests/src/android/net/util/ConnectivityPacketSummaryTest.java
+++ b/packages/NetworkStack/tests/unit/src/android/net/util/ConnectivityPacketSummaryTest.java
diff --git a/packages/NetworkStack/tests/src/android/net/util/PacketReaderTest.java b/packages/NetworkStack/tests/unit/src/android/net/util/PacketReaderTest.java
index 289dcade99a6..289dcade99a6 100644
--- a/packages/NetworkStack/tests/src/android/net/util/PacketReaderTest.java
+++ b/packages/NetworkStack/tests/unit/src/android/net/util/PacketReaderTest.java
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
index 26186751c282..832b7124dc05 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -297,6 +297,7 @@ public class NetworkMonitorTest {
setOtherFallbackUrls(TEST_OTHER_FALLBACK_URL);
setFallbackSpecs(null); // Test with no fallback spec by default
when(mRandom.nextInt()).thenReturn(0);
+
// DNS probe timeout should not be defined more than half of HANDLER_TIMEOUT_MS. Otherwise,
// it will fail the test because of timeout expired for querying AAAA and A sequentially.
when(mResources.getInteger(eq(R.integer.config_captive_portal_dns_probe_timeout)))
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java b/packages/NetworkStack/tests/unit/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
index 87346e5d6a28..87346e5d6a28 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
+++ b/packages/NetworkStack/tests/unit/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java b/packages/NetworkStack/tests/unit/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java
index 3d3aabc66e70..3d3aabc66e70 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java
+++ b/packages/NetworkStack/tests/unit/src/com/android/server/connectivity/ipmemorystore/RelevanceUtilsTests.java
diff --git a/packages/NetworkStack/tests/src/com/android/server/util/SharedLogTest.java b/packages/NetworkStack/tests/unit/src/com/android/server/util/SharedLogTest.java
index b1db051d2bd8..b1db051d2bd8 100644
--- a/packages/NetworkStack/tests/src/com/android/server/util/SharedLogTest.java
+++ b/packages/NetworkStack/tests/unit/src/com/android/server/util/SharedLogTest.java
diff --git a/packages/PackageInstaller/res/values-bs/strings.xml b/packages/PackageInstaller/res/values-bs/strings.xml
index 329e940056fa..ebf0685fd295 100644
--- a/packages/PackageInstaller/res/values-bs/strings.xml
+++ b/packages/PackageInstaller/res/values-bs/strings.xml
@@ -40,7 +40,7 @@
<string name="unknown_apps_admin_dlg_text" msgid="4456572224020176095">"Vaš administrator ne dozvoljava instaliranje aplikacija iz nepoznatih izvora"</string>
<string name="unknown_apps_user_restriction_dlg_text" msgid="151020786933988344">"Ovaj korisnik ne može instalirati nepoznate aplikacije"</string>
<string name="install_apps_user_restriction_dlg_text" msgid="2154119597001074022">"Ovom korisniku nije dozvoljeno instaliranje aplikacija"</string>
- <string name="ok" msgid="7871959885003339302">"UREDU"</string>
+ <string name="ok" msgid="7871959885003339302">"Uredu"</string>
<string name="manage_applications" msgid="5400164782453975580">"Uprav. aplik."</string>
<string name="out_of_space_dlg_title" msgid="4156690013884649502">"Nedostatak prostora"</string>
<string name="out_of_space_dlg_text" msgid="8727714096031856231">"Ne možete instalirati aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>. Oslobodite prostor u pohrani i pokušajte ponovo."</string>
diff --git a/packages/PackageInstaller/res/values-eu/strings.xml b/packages/PackageInstaller/res/values-eu/strings.xml
index 9c23097b7f23..dbcb2bb431f2 100644
--- a/packages/PackageInstaller/res/values-eu/strings.xml
+++ b/packages/PackageInstaller/res/values-eu/strings.xml
@@ -83,9 +83,9 @@
<string name="untrusted_external_source_warning" product="tablet" msgid="6539403649459942547">"Segurtasuna bermatzeko, ezin dira instalatu iturburu honetako aplikazio ezezagunak tableta honetan."</string>
<string name="untrusted_external_source_warning" product="tv" msgid="1206648674551321364">"Segurtasuna bermatzeko, ezin dira instalatu iturburu honetako aplikazio ezezagunak telebista honetan."</string>
<string name="untrusted_external_source_warning" product="default" msgid="7279739265754475165">"Segurtasuna bermatzeko, ezin dira instalatu iturburu honetako aplikazio ezezagunak telefono honetan."</string>
- <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Telefonoak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartu egingo duzu zeu zarela hura erabiltzeagatik telefonoak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
- <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Tabletak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartu egingo duzu zeu zarela hura erabiltzeagatik tabletak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
- <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Telebistak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartu egingo duzu zeu zarela hura erabiltzeagatik telebistak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
+ <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"Telefonoak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartu egingo duzu zu zarela hura erabiltzeagatik telefonoak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
+ <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"Tabletak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartu egingo duzu zu zarela hura erabiltzeagatik tabletak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
+ <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"Telebistak eta datu pertsonalek aplikazio ezezagunen erasoak jaso ditzakete. Aplikazio hau instalatzen baduzu, onartu egingo duzu zu zarela hura erabiltzeagatik telebistak jasan ditzakeen kalteen edo datu-galeren erantzulea."</string>
<string name="anonymous_source_continue" msgid="4375745439457209366">"Egin aurrera"</string>
<string name="external_sources_settings" msgid="4046964413071713807">"Ezarpenak"</string>
<string name="wear_app_channel" msgid="1960809674709107850">"Wear aplikazioak instalatzea/desinstalatzea"</string>
diff --git a/packages/PrintSpooler/res/values-fr/strings.xml b/packages/PrintSpooler/res/values-fr/strings.xml
index 3c2aec3c8bd2..f6e901de8393 100644
--- a/packages/PrintSpooler/res/values-fr/strings.xml
+++ b/packages/PrintSpooler/res/values-fr/strings.xml
@@ -65,7 +65,7 @@
<string name="notification_channel_failure" msgid="9042250774797916414">"Tâches d\'impression non abouties"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Impossible de créer le fichier"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Certains services d\'impression sont désactivés."</string>
- <string name="print_searching_for_printers" msgid="6550424555079932867">"Recherche d\'imprimantes en cours"</string>
+ <string name="print_searching_for_printers" msgid="6550424555079932867">"Recherche d\'imprimantes..."</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Aucun service d\'impression activé"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Aucune imprimante trouvée"</string>
<string name="cannot_add_printer" msgid="7840348733668023106">"Impossible d\'ajouter des imprimantes"</string>
diff --git a/packages/PrintSpooler/res/values-hi/strings.xml b/packages/PrintSpooler/res/values-hi/strings.xml
index 6f9807028d5b..2637c3c0b562 100644
--- a/packages/PrintSpooler/res/values-hi/strings.xml
+++ b/packages/PrintSpooler/res/values-hi/strings.xml
@@ -34,7 +34,7 @@
<string name="print_preview" msgid="8010217796057763343">"प्रिंट की झलक"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"झलक देखने के लिए PDF व्यूअर इंस्टॉल करें"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"प्रिंटिंग ऐप बंद हो गया"</string>
- <string name="generating_print_job" msgid="3119608742651698916">"प्रिंट कार्य जनरेट हो रहा है"</string>
+ <string name="generating_print_job" msgid="3119608742651698916">"प्रिंट जॉ जनरेट हो रहा है"</string>
<string name="save_as_pdf" msgid="5718454119847596853">"पीडीएफ़ के तौर पर सेव करें"</string>
<string name="all_printers" msgid="5018829726861876202">"सभी प्रिंटर..."</string>
<string name="print_dialog" msgid="32628687461331979">"प्रिंट डॉयलॉग"</string>
@@ -61,8 +61,8 @@
</plurals>
<string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
<string name="printer_info_desc" msgid="7181988788991581654">"इस प्रिंटर के बारे में ज़्यादा जानकारी"</string>
- <string name="notification_channel_progress" msgid="872788690775721436">"चल रहे प्रिंट कार्य"</string>
- <string name="notification_channel_failure" msgid="9042250774797916414">"असफल रहे प्रिंट कार्य"</string>
+ <string name="notification_channel_progress" msgid="872788690775721436">"चल रहे प्रिंट जॉ"</string>
+ <string name="notification_channel_failure" msgid="9042250774797916414">"असफल रहे प्रिंट जॉ"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"फ़ाइल नहीं बनाई जा सकी"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"कुछ प्रिंट सेवाएं अक्षम हैं"</string>
<string name="print_searching_for_printers" msgid="6550424555079932867">"प्रिंटर सर्च कर रहा है"</string>
diff --git a/packages/PrintSpooler/res/values-my/strings.xml b/packages/PrintSpooler/res/values-my/strings.xml
index 34297b657047..fdcdd7cdb0df 100644
--- a/packages/PrintSpooler/res/values-my/strings.xml
+++ b/packages/PrintSpooler/res/values-my/strings.xml
@@ -86,7 +86,7 @@
<string name="cancel" msgid="4373674107267141885">"မလုပ်တော့"</string>
<string name="restart" msgid="2472034227037808749">"ပြန်စရန်"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"စာထုတ်စက်နဲ့ ဆက်သွယ်ထားမှု မရှိပါ"</string>
- <string name="reason_unknown" msgid="5507940196503246139">"မသိပါ"</string>
+ <string name="reason_unknown" msgid="5507940196503246139">"မသိ"</string>
<string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g>ကိုသုံးမလား။"</string>
<string name="print_service_security_warning_summary" msgid="1427434625361692006">"သင်၏ စာရွက်စာတမ်းများသည် ပရင်တာထံသို့ သွားစဉ် ဆာဗာ တစ်ခု သို့မဟုတ် ပိုများပြီး ဖြတ်ကျော်နိုင်ရသည်။"</string>
<string-array name="color_mode_labels">
@@ -99,7 +99,7 @@
<item msgid="79513688117503758">"အနားသတ် အတို"</item>
</string-array>
<string-array name="orientation_labels">
- <item msgid="4061931020926489228">"ထောင်လိုက်"</item>
+ <item msgid="4061931020926489228">"ဒေါင်လိုက်"</item>
<item msgid="3199660090246166812">"အလျားလိုက်"</item>
</string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"ဖိုင်သို့ မရေးနိုင်ခဲ့"</string>
diff --git a/packages/PrintSpooler/res/values-pl/strings.xml b/packages/PrintSpooler/res/values-pl/strings.xml
index a960fe206a58..0b310f00a50b 100644
--- a/packages/PrintSpooler/res/values-pl/strings.xml
+++ b/packages/PrintSpooler/res/values-pl/strings.xml
@@ -67,7 +67,7 @@
<string name="notification_channel_failure" msgid="9042250774797916414">"Nieudane zadania drukowania"</string>
<string name="could_not_create_file" msgid="3425025039427448443">"Nie udało się utworzyć pliku"</string>
<string name="print_services_disabled_toast" msgid="9089060734685174685">"Niektóre usługi drukowania są wyłączone"</string>
- <string name="print_searching_for_printers" msgid="6550424555079932867">"Szukanie drukarek"</string>
+ <string name="print_searching_for_printers" msgid="6550424555079932867">"Szukam drukarek"</string>
<string name="print_no_print_services" msgid="8561247706423327966">"Brak włączonych usług drukowania"</string>
<string name="print_no_printers" msgid="4869403323900054866">"Nie znaleziono drukarek"</string>
<string name="cannot_add_printer" msgid="7840348733668023106">"Nie można dodawać drukarek"</string>
diff --git a/packages/PrintSpooler/res/values-ta/strings.xml b/packages/PrintSpooler/res/values-ta/strings.xml
index 77737183452e..4bb167a07010 100644
--- a/packages/PrintSpooler/res/values-ta/strings.xml
+++ b/packages/PrintSpooler/res/values-ta/strings.xml
@@ -87,7 +87,7 @@
<string name="restart" msgid="2472034227037808749">"மீண்டும் தொடங்கு"</string>
<string name="no_connection_to_printer" msgid="2159246915977282728">"அச்சுப்பொறியுடன் இணைக்கப்படவில்லை"</string>
<string name="reason_unknown" msgid="5507940196503246139">"அறியப்படாதது"</string>
- <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g>ஐப் பயன்படுத்தவா?"</string>
+ <string name="print_service_security_warning_title" msgid="2160752291246775320">"<xliff:g id="SERVICE">%1$s</xliff:g> ஐப் பயன்படுத்தவா?"</string>
<string name="print_service_security_warning_summary" msgid="1427434625361692006">"உங்கள் ஆவணம் பிரிண்டருக்குச் செல்லும் வழியில் ஒன்று அல்லது அதற்கு மேற்பட்ட சேவையகங்களைக் கடந்து செல்லக்கூடும்."</string>
<string-array name="color_mode_labels">
<item msgid="7602948745415174937">"கருப்பு &amp; வெள்ளை"</item>
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/Estimate.kt b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/Estimate.kt
index 786139ffc790..b2e75ea6867f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/Estimate.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/Estimate.kt
@@ -77,5 +77,17 @@ class Estimate(
Settings.Global.putLong(resolver, Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME,
System.currentTimeMillis())
}
+
+ /**
+ * Returns when the estimate was last updated as an Instant
+ */
+ @JvmStatic
+ fun getLastCacheUpdateTime(context: Context): Instant {
+ return Instant.ofEpochMilli(
+ Settings.Global.getLong(
+ context.contentResolver,
+ Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME,
+ -1))
+ }
}
}
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index dd72d5779c19..05246a42dedc 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -235,4 +235,7 @@
<!-- Default for Settings.Secure.SILENCE_GESTURE -->
<bool name="def_silence_gesture">false</bool>
+
+ <!-- Default for Settings.Secure.AWARE_LOCK_ENABLED -->
+ <bool name="def_aware_lock_enabled">false</bool>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 6558c87aaf3a..f7132e368e94 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3237,7 +3237,7 @@ public class SettingsProvider extends ContentProvider {
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 180;
+ private static final int SETTINGS_VERSION = 181;
private final int mUserId;
@@ -4401,6 +4401,25 @@ public class SettingsProvider extends ContentProvider {
currentVersion = 180;
}
+ if (currentVersion == 180) {
+ // Version 180: Set the default value for Secure Settings: AWARE_LOCK_ENABLED
+
+ final SettingsState secureSettings = getSecureSettingsLocked(userId);
+
+ final Setting awareLockEnabled = secureSettings.getSettingLocked(
+ Secure.AWARE_LOCK_ENABLED);
+
+ if (awareLockEnabled.isNull()) {
+ final boolean defAwareLockEnabled = getContext().getResources().getBoolean(
+ R.bool.def_aware_lock_enabled);
+ secureSettings.insertSettingLocked(
+ Secure.AWARE_LOCK_ENABLED, defAwareLockEnabled ? "1" : "0",
+ null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+
+ currentVersion = 181;
+ }
+
// vXXX: Add new settings above this point.
if (currentVersion != newVersion) {
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 0fa415522f6b..e00f204945c1 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -198,6 +198,12 @@
<!-- Permission required to test ContentResolver caching. -->
<uses-permission android:name="android.permission.CACHE_CONTENT" />
+ <!-- Permission required to test ExplicitHealthCheckServiceImpl. -->
+ <uses-permission android:name="android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE" />
+
+ <!-- Permission required for CTS test - CrossProfileAppsHostSideTest -->
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_PROFILES"/>
+
<application android:label="@string/app_label"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true">
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
index a84ddaf29e52..4db2280fdc0a 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
@@ -34,7 +34,6 @@
android:layout_height="wrap_content"
android:paddingStart="44dp"
android:paddingEnd="44dp"
- android:letterSpacing="0.02"
android:visibility="gone"
android:textColor="?attr/wallpaperTextColor"
android:theme="@style/TextAppearance.Keyguard"
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index 137c30aefd33..1c8e141a61f8 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -115,7 +115,6 @@
<item name="android:layout_height">wrap_content</item>
<item name="android:lines">1</item>
<item name="android:textSize">@dimen/widget_label_font_size</item>
- <item name="android:letterSpacing">0.02</item>
</style>
<style name="TextAppearance.Keyguard.BottomArea">
diff --git a/packages/SystemUI/res/drawable-night/status_bar_notification_section_header_clear_btn.xml b/packages/SystemUI/res/drawable-night/status_bar_notification_section_header_clear_btn.xml
deleted file mode 100644
index c471b38306d5..000000000000
--- a/packages/SystemUI/res/drawable-night/status_bar_notification_section_header_clear_btn.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2019 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="40dp"
- android:height="40dp"
- android:viewportWidth="40"
- android:viewportHeight="40">
- <path
- android:fillColor="#9AA0A6"
- android:pathData="M24.6667 16.2733L23.7267 15.3333L20 19.06L16.2734 15.3333L15.3334 16.2733L19.06 20L15.3334 23.7266L16.2734 24.6666L20 20.94L23.7267 24.6666L24.6667 23.7266L20.94 20L24.6667 16.2733Z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/corner_gesture_hint.xml b/packages/SystemUI/res/drawable/corner_gesture_hint.xml
new file mode 100644
index 000000000000..3f4abb0e0dd4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/corner_gesture_hint.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT 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:height="12dp"
+ android:width="12dp"
+ android:viewportWidth="12"
+ android:viewportHeight="12">
+
+ <path android:fillColor="#00000000"
+ android:pathData="M 1.18 10.65 C 1.18 5.58 5.41 1.18 10.65 1.18"
+ android:strokeColor="#000"
+ android:strokeLineCap="round"
+ android:strokeWidth="1.3" />
+</vector>
diff --git a/packages/SystemUI/res/drawable/status_bar_notification_section_header_clear_btn.xml b/packages/SystemUI/res/drawable/status_bar_notification_section_header_clear_btn.xml
index 15f14d8af89b..8b3408048848 100644
--- a/packages/SystemUI/res/drawable/status_bar_notification_section_header_clear_btn.xml
+++ b/packages/SystemUI/res/drawable/status_bar_notification_section_header_clear_btn.xml
@@ -20,6 +20,6 @@
android:viewportWidth="40"
android:viewportHeight="40">
<path
- android:fillColor="#5F6368"
+ android:fillColor="@color/notification_section_clear_all_btn_color"
android:pathData="M24.6667 16.2733L23.7267 15.3333L20 19.06L16.2734 15.3333L15.3334 16.2733L19.06 20L15.3334 23.7267L16.2734 24.6667L20 20.94L23.7267 24.6667L24.6667 23.7267L20.94 20L24.6667 16.2733Z"/>
</vector>
diff --git a/packages/SystemUI/res/layout/bubble_expanded_view.xml b/packages/SystemUI/res/layout/bubble_expanded_view.xml
index 5b93edd1e6b3..db40c4fde053 100644
--- a/packages/SystemUI/res/layout/bubble_expanded_view.xml
+++ b/packages/SystemUI/res/layout/bubble_expanded_view.xml
@@ -30,11 +30,12 @@
<com.android.systemui.statusbar.AlphaOptimizedButton
style="@android:style/Widget.Material.Button.Borderless"
android:id="@+id/settings_button"
- android:layout_gravity="end"
+ android:layout_gravity="start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="true"
android:text="@string/manage_bubbles_text"
- android:textColor="?attr/wallpaperTextColor"/>
+ android:textColor="?attr/wallpaperTextColor"
+ />
</com.android.systemui.bubbles.BubbleExpandedView>
diff --git a/packages/SystemUI/res/layout/contaminant_dialog.xml b/packages/SystemUI/res/layout/contaminant_dialog.xml
new file mode 100644
index 000000000000..ea6d900e8fa7
--- /dev/null
+++ b/packages/SystemUI/res/layout/contaminant_dialog.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/layout/alert_dialog.xml
+**
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/parentPanel"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="18dp"
+ android:paddingBottom="18dp"
+ android:textAlignment="center"
+ android:fontFamily="google-sans-medium"
+ android:textSize="20sp"
+ android:textStyle="bold"
+ android:textColor="?android:attr/textColorPrimary"/>
+
+ <TextView
+ android:id="@+id/message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="24dp"
+ android:paddingRight="24dp"
+ android:paddingBottom="24dp"
+ android:textAlignment="center"
+ android:textSize="16sp"
+ android:fontFamily="roboto-regular"
+ android:textColor="?android:attr/textColorPrimary" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingBottom="8dp"
+ android:focusable="true">
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="2dp"
+ android:background="@android:drawable/divider_horizontal_bright" />
+
+ <TextView
+ android:id="@+id/learnMore"
+ style="@style/USBContaminant.UserAction" />
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="2dp"
+ android:background="@android:drawable/divider_horizontal_bright" />
+
+ <TextView
+ android:id="@+id/enableUsb"
+ style="@style/USBContaminant.UserAction" />
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="2dp"
+ android:background="@android:drawable/divider_horizontal_bright" />
+
+ <TextView
+ android:id="@+id/gotIt"
+ style="@style/USBContaminant.UserAction" />
+
+ </LinearLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 087e0bd8089f..4b672ee0733f 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -228,7 +228,7 @@ asked for it -->
android:focusable="true">
<ImageView
android:id="@+id/alert_icon"
- android:src="@drawable/ic_notification_interruptive"
+ android:src="@drawable/ic_notifications_alert"
android:background="@android:color/transparent"
android:layout_gravity="center"
android:layout_width="wrap_content"
@@ -249,6 +249,7 @@ asked for it -->
android:text="@string/notification_alert_title"/>
<TextView
android:id="@+id/alert_summary"
+ android:visibility="gone"
android:paddingTop="@dimen/notification_importance_button_padding"
android:text="@string/notification_channel_summary_default"
android:layout_width="match_parent"
@@ -271,7 +272,7 @@ asked for it -->
android:focusable="true">
<ImageView
android:id="@+id/silence_icon"
- android:src="@drawable/ic_notification_gentle"
+ android:src="@drawable/ic_notifications_silence"
android:background="@android:color/transparent"
android:layout_gravity="center"
android:layout_width="wrap_content"
@@ -292,6 +293,7 @@ asked for it -->
android:text="@string/notification_silence_title"/>
<TextView
android:id="@+id/silence_summary"
+ android:visibility="gone"
android:paddingTop="@dimen/notification_importance_button_padding"
android:text="@string/notification_channel_summary_default"
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/qs_customize_header.xml b/packages/SystemUI/res/layout/qs_customize_header.xml
index 58066a3ef19c..481561d74138 100644
--- a/packages/SystemUI/res/layout/qs_customize_header.xml
+++ b/packages/SystemUI/res/layout/qs_customize_header.xml
@@ -20,7 +20,6 @@
android:id="@android:id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginBottom="@dimen/qs_tile_margin_top_bottom_negative"
android:gravity="center"
android:minHeight="@dimen/qs_customize_header_min_height"
android:textAppearance="@style/TextAppearance.QSEdit.Headers"
diff --git a/packages/SystemUI/res/layout/quick_settings_header_info.xml b/packages/SystemUI/res/layout/quick_settings_header_info.xml
index d0783a047895..1e16e5d12b83 100644
--- a/packages/SystemUI/res/layout/quick_settings_header_info.xml
+++ b/packages/SystemUI/res/layout/quick_settings_header_info.xml
@@ -14,7 +14,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/header_text_container"
android:layout_width="match_parent"
android:layout_height="@dimen/qs_header_tooltip_height"
@@ -23,25 +23,16 @@
android:paddingEnd="@dimen/status_bar_padding_end"
android:theme="@style/QSHeaderTheme">
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="start|center_vertical"
- android:gravity="center_vertical">
-
- <LinearLayout
+ <com.android.systemui.qs.QSHeaderInfoLayout
android:id="@+id/status_container"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="start|center_vertical"
+ android:layout_width="match_parent"
android:layout_weight="1"
- android:gravity="center_vertical" >
+ android:layout_height="match_parent">
<LinearLayout
android:id = "@+id/alarm_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:focusable="true"
android:clickable="true">
@@ -76,7 +67,6 @@
android:id = "@+id/ringer_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:focusable="true"
android:clickable="true">
@@ -98,21 +88,14 @@
android:textAppearance="@style/TextAppearance.QS.Status"
android:visibility="gone"/>
</LinearLayout>
- </LinearLayout>
-
- <View
- android:minWidth="@dimen/qs_status_separator"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"/>
-
+ </com.android.systemui.qs.QSHeaderInfoLayout>
<include layout="@layout/qs_carrier_group"
android:id="@+id/carrier_group"
android:layout_width="wrap_content"
android:layout_height="match_parent"
+ android:layout_marginStart="@dimen/qs_status_separator"
android:layout_gravity="end|center_vertical"
android:focusable="false"/>
- </LinearLayout>
-</FrameLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/rounded_corners.xml b/packages/SystemUI/res/layout/rounded_corners.xml
index 26cf7920c35b..02651a212816 100644
--- a/packages/SystemUI/res/layout/rounded_corners.xml
+++ b/packages/SystemUI/res/layout/rounded_corners.xml
@@ -32,4 +32,22 @@
android:tint="#ff000000"
android:layout_gravity="right|bottom"
android:src="@drawable/rounded" />
+ <ImageView
+ android:id="@+id/assist_hint_left"
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:padding="6dp"
+ android:layout_gravity="left|top"
+ android:src="@drawable/corner_gesture_hint"
+ android:tint="#ffffffff"
+ android:visibility="gone" />
+ <ImageView
+ android:id="@+id/assist_hint_right"
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:padding="6dp"
+ android:layout_gravity="right|bottom"
+ android:src="@drawable/corner_gesture_hint"
+ android:tint="#ffffffff"
+ android:visibility="gone" />
</com.android.systemui.RegionInterceptingFrameLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_section_header.xml b/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
index 2b210064023b..0c3c597a7b3a 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
@@ -43,7 +43,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:layout_marginLeft="@dimen/notification_section_header_padding_left"
+ android:layout_marginStart="@dimen/notification_section_header_padding_left"
android:text="@string/notification_section_header_gentle"
android:textSize="12sp"
android:textColor="@color/notification_section_header_label_color"
@@ -52,9 +52,10 @@
android:id="@+id/btn_clear_all"
android:layout_width="@dimen/notification_section_header_height"
android:layout_height="@dimen/notification_section_header_height"
- android:layout_marginRight="4dp"
+ android:layout_marginEnd="4dp"
android:src="@drawable/status_bar_notification_section_header_clear_btn"
android:contentDescription="@string/accessibility_notification_section_header_gentle_clear_all"
+ android:scaleType="center"
/>
</LinearLayout>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index e25faa28d658..addc10aaeff6 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -50,6 +50,7 @@
<color name="notification_guts_button_color">@color/GM2_blue_200</color>
<color name="notification_section_header_label_color">@color/GM2_grey_200</color>
+ <color name="notification_section_clear_all_btn_color">@color/GM2_grey_500</color>
<color name="notification_channel_dialog_separator">@color/GM2_grey_700</color>
<!-- The color of the background in the top part of QSCustomizer -->
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index d4bf9cd18510..9b72e7a96cbf 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -151,5 +151,11 @@
<attr name="optedOut" format="boolean" />
</declare-styleable>
+ <!-- Theme attributes used to style the appearance of expanded Bubbles -->
+ <declare-styleable name="BubbleExpandedView">
+ <attr name="android:colorBackgroundFloating" />
+ <attr name="android:dialogCornerRadius" />
+ </declare-styleable>
+
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 6d7e20594912..490473ce003a 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -98,6 +98,7 @@
<color name="notification_guts_button_color">@color/GM2_blue_700</color>
<color name="notification_section_header_label_color">@color/GM2_grey_900</color>
+ <color name="notification_section_clear_all_btn_color">@color/GM2_grey_700</color>
<!-- The divider view for the notification channel editor half-shelf -->
<color name="notification_channel_dialog_separator">@color/GM2_grey_200</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e00e5f23dea8..fb226c7540bb 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -442,8 +442,11 @@
<dimen name="qs_tile_margin_vertical">24dp</dimen>
<dimen name="qs_tile_margin_top_bottom">12dp</dimen>
<dimen name="qs_tile_margin_top_bottom_negative">-12dp</dimen>
- <!-- The height of the qs customize header. Should be (28dp - qs_tile_margin_top_bottom). -->
- <dimen name="qs_customize_header_min_height">40dp</dimen>
+ <!-- The height of the qs customize header. Should be
+ (qs_panel_padding_top (48dp) + brightness_mirror_height (48dp) + qs_tile_margin_top (18dp)) -
+ (Toolbar_minWidth (56dp) + qs_tile_margin_top_bottom (12dp))
+ -->
+ <dimen name="qs_customize_header_min_height">46dp</dimen>
<dimen name="qs_tile_margin_top">18dp</dimen>
<dimen name="qs_tile_background_size">44dp</dimen>
<dimen name="qs_quick_tile_size">48dp</dimen>
@@ -698,7 +701,7 @@
<!-- The top padding of the clear all button -->
<dimen name="clear_all_padding_top">12dp</dimen>
- <dimen name="notification_section_header_height">40dp</dimen>
+ <dimen name="notification_section_header_height">48dp</dimen>
<dimen name="notification_section_header_padding_left">16dp</dimen>
<!-- Largest size an avatar might need to be drawn in the user picker, status bar, or
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c95dbfeac17e..98312505b80d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -166,7 +166,7 @@
<string name="usb_contaminant_title">USB port disabled</string>
<!-- Message of USB contaminant presence dialog [CHAR LIMIT=NONE] -->
- <string name="usb_contaminant_message">To protect your device from liquid or debris, the USB port is disabled and won\u2019t detect any accessories.\n\nYou\u2019ll be notified when it\u2019s safe to use the USB port again.</string>
+ <string name="usb_contaminant_message">To protect your device from liquid or debris, the USB port is disabled and won\u2019t detect any accessories.\n\nYou\u2019ll be notified when it\u2019s okay to use the USB port again.</string>
<!-- Toast for enabling ports from USB contaminant dialog [CHAR LIMIT=NONE] -->
<string name="usb_port_enabled">USB port enabled to detect chargers and accessories</string>
@@ -174,6 +174,9 @@
<!-- Button text to disable contaminant detection [CHAR LIMIT=NONE] -->
<string name="usb_disable_contaminant_detection">Enable USB</string>
+ <!-- Button text to disable contaminant detection [CHAR LIMIT=NONE] -->
+ <string name="learn_more">Learn more</string>
+
<!-- Checkbox label for application compatibility mode ON (zooming app to look like it's running
on a phone). [CHAR LIMIT=25] -->
<string name="compat_mode_on">Zoom to fill screen</string>
@@ -1118,10 +1121,10 @@
<string name="manage_notifications_text">Manage</string>
<!-- Section title for notifications that do not vibrate or make noise. [CHAR LIMIT=40] -->
- <string name="notification_section_header_gentle">Gentle notifications</string>
+ <string name="notification_section_header_gentle">Silent notifications</string>
<!-- Content description for accessibility: Tapping this button will dismiss all gentle notifications [CHAR LIMIT=NONE] -->
- <string name="accessibility_notification_section_header_gentle_clear_all">Clear all gentle notifications</string>
+ <string name="accessibility_notification_section_header_gentle_clear_all">Clear all silent notifications</string>
<!-- The text to show in the notifications shade when dnd is suppressing notifications. [CHAR LIMIT=100] -->
<string name="dnd_suppressing_shade_text">Notifications paused by Do Not Disturb</string>
@@ -1656,13 +1659,13 @@
<string name="inline_minimize_button">Minimize</string>
<!-- Notification inline controls: button to show notifications silently, without alerting the user [CHAR_LIMIT=35] -->
- <string name="inline_silent_button_silent">Gentle</string>
+ <string name="inline_silent_button_silent">Silent</string>
<!-- Notification inline controls: button to continue showing notifications silently [CHAR_LIMIT=35] -->
<string name="inline_silent_button_stay_silent">Stay silent</string>
<!-- Notification inline controls: button to make notifications alert the user [CHAR_LIMIT=35] -->
- <string name="inline_silent_button_alert">Interruptive</string>
+ <string name="inline_silent_button_alert">Alerting</string>
<!-- Notification inline controls: button to continue alerting the user when notifications arrive [CHAR_LIMIT=35] -->
<string name="inline_silent_button_keep_alerting">Keep alerting</string>
@@ -2375,7 +2378,7 @@
<string name="auto_saver_title">Tap to schedule Battery Saver</string>
<!-- The content of the notification to suggest enabling automatic battery saver. [CHAR LIMIT=NONE]-->
- <string name="auto_saver_text">Turn on automatically when battery is at <xliff:g id="percentage">%d</xliff:g>%%</string>
+ <string name="auto_saver_text">Turn on when battery is likely to run out</string>
<!-- An action on the notification to suggest enabling automatic battery saver: Do not turn on automatic battery saver. [CHAR LIMIT=NONE]-->
<string name="no_auto_saver_action">No thanks</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 59ed5cea2169..04cd30cdb86a 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -572,4 +572,22 @@
<item name="android:backgroundDimEnabled">true</item>
<item name="android:windowCloseOnTouchOutside">true</item>
</style>
+
+ <!-- USB Contaminant dialog -->
+ <style name ="USBContaminant" />
+
+ <style name ="USBContaminant.UserAction">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:fontFamily">roboto-regular</item>
+ <item name="android:paddingLeft">16dp</item>
+ <item name="android:paddingTop">16dp</item>
+ <item name="android:paddingRight">24dp</item>
+ <item name="android:paddingBottom">16dp</item>
+ <item name="android:textAlignment">viewStart</item>
+ <item name="android:textSize">16sp</item>
+ <item name="android:clickable">true</item>
+ <item name="android:background">?android:attr/selectableItemBackground</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ </style>
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index b826b30f3245..77bb5141d1e0 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -73,6 +73,12 @@ interface ISystemUiProxy {
void onAssistantProgress(float progress) = 12;
/**
+ * Proxies the assistant gesture fling velocity (in pixels per millisecond) upon completion.
+ * Velocity is 0 for drag gestures.
+ */
+ void onAssistantGestureCompletion(float velocity) = 18;
+
+ /**
* Start the assistant.
*/
void startAssistant(in Bundle bundle) = 13;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index b89b9ef3cad7..cc3a67cd2788 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -28,6 +28,7 @@ import com.android.internal.policy.ScreenDecorationsUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.StringJoiner;
/**
* Various shared constants between Launcher and SysUI as part of quickstep
@@ -35,7 +36,6 @@ import java.lang.annotation.RetentionPolicy;
public class QuickStepContract {
public static final String KEY_EXTRA_SYSUI_PROXY = "extra_sysui_proxy";
- public static final String KEY_EXTRA_INPUT_CHANNEL = "extra_input_channel";
public static final String KEY_EXTRA_INPUT_MONITOR = "extra_input_monitor";
public static final String KEY_EXTRA_WINDOW_CORNER_RADIUS = "extra_window_corner_radius";
public static final String KEY_EXTRA_SUPPORTS_WINDOW_CORNERS = "extra_supports_window_corners";
@@ -47,12 +47,26 @@ public class QuickStepContract {
public static final String NAV_BAR_MODE_GESTURAL_OVERLAY =
WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
+ // Overview is disabled, either because the device is in lock task mode, or because the device
+ // policy has disabled the feature
public static final int SYSUI_STATE_SCREEN_PINNING = 1 << 0;
+ // The navigation bar is hidden due to immersive mode
public static final int SYSUI_STATE_NAV_BAR_HIDDEN = 1 << 1;
+ // The notification panel is expanded and interactive (either locked or unlocked), and the
+ // quick settings is not expanded
public static final int SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED = 1 << 2;
+ // The keyguard bouncer is showing
public static final int SYSUI_STATE_BOUNCER_SHOWING = 1 << 3;
+ // The navigation bar a11y button should be shown
public static final int SYSUI_STATE_A11Y_BUTTON_CLICKABLE = 1 << 4;
+ // The navigation bar a11y button shortcut is available
public static final int SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE = 1 << 5;
+ // The keyguard is showing
+ public static final int SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING = 1 << 6;
+ // The recents feature is disabled (either by SUW/SysUI/device policy)
+ public static final int SYSUI_STATE_OVERVIEW_DISABLED = 1 << 7;
+ // The home feature is disabled (either by SUW/SysUI/device policy)
+ public static final int SYSUI_STATE_HOME_DISABLED = 1 << 8;
@Retention(RetentionPolicy.SOURCE)
@IntDef({SYSUI_STATE_SCREEN_PINNING,
@@ -60,10 +74,27 @@ public class QuickStepContract {
SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED,
SYSUI_STATE_BOUNCER_SHOWING,
SYSUI_STATE_A11Y_BUTTON_CLICKABLE,
- SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE
+ SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE,
+ SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING,
+ SYSUI_STATE_OVERVIEW_DISABLED,
+ SYSUI_STATE_HOME_DISABLED
})
public @interface SystemUiStateFlags {}
+ public static String getSystemUiStateString(int flags) {
+ StringJoiner str = new StringJoiner("|");
+ str.add((flags & SYSUI_STATE_SCREEN_PINNING) != 0 ? "screen_pinned" : "");
+ str.add((flags & SYSUI_STATE_OVERVIEW_DISABLED) != 0 ? "overview_disabled" : "");
+ str.add((flags & SYSUI_STATE_HOME_DISABLED) != 0 ? "home_disabled" : "");
+ str.add((flags & SYSUI_STATE_NAV_BAR_HIDDEN) != 0 ? "navbar_hidden" : "");
+ str.add((flags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0 ? "notif_visible" : "");
+ str.add((flags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING) != 0 ? "keygrd_visible" : "");
+ str.add((flags & SYSUI_STATE_BOUNCER_SHOWING) != 0 ? "bouncer_visible" : "");
+ str.add((flags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0 ? "a11y_click" : "");
+ str.add((flags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0 ? "a11y_long_click" : "");
+ return str.toString();
+ }
+
/**
* Touch slopes and thresholds for quick step operations. Drag slop is the point where the
* home button press/long press over are ignored and will start to drag when exceeded and the
@@ -87,6 +118,37 @@ public class QuickStepContract {
}
/**
+ * Returns whether the specified sysui state is such that the assistant gesture should be
+ * disabled.
+ */
+ public static boolean isAssistantGestureDisabled(int sysuiStateFlags) {
+ // Disable when in screen pinning, immersive, the bouncer is showing, or the notifications
+ // are interactive
+ int disableFlags = SYSUI_STATE_SCREEN_PINNING
+ | SYSUI_STATE_NAV_BAR_HIDDEN
+ | SYSUI_STATE_BOUNCER_SHOWING
+ | SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
+ return (sysuiStateFlags & disableFlags) != 0;
+ }
+
+ /**
+ * Returns whether the specified sysui state is such that the back gesture should be
+ * disabled.
+ */
+ public static boolean isBackGestureDisabled(int sysuiStateFlags) {
+ // Always allow when the bouncer is showing (even on top of the keyguard)
+ if ((sysuiStateFlags & SYSUI_STATE_BOUNCER_SHOWING) != 0) {
+ return false;
+ }
+ // Disable when in screen pinning, immersive, or the notifications are interactive
+ int disableFlags = SYSUI_STATE_SCREEN_PINNING
+ | SYSUI_STATE_NAV_BAR_HIDDEN
+ | SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
+ | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
+ return (sysuiStateFlags & disableFlags) != 0;
+ }
+
+ /**
* @return whether this nav bar mode is edge to edge
*/
public static boolean isGesturalMode(int mode) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index d0b2c58e8021..0bb9e744f2b6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -3,6 +3,7 @@ package com.android.keyguard;
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.app.WallpaperManager;
import android.content.Context;
@@ -412,15 +413,10 @@ public class KeyguardClockSwitch extends RelativeLayout {
mClockTransition.setScale(smallFontSize / bigFontSize);
mBoldClockTransition.setScale(bigFontSize / smallFontSize);
- TransitionManager.beginDelayedTransition((ViewGroup) mClockView.getParent(), mTransition);
- mClockView.setVisibility(hasHeader ? View.INVISIBLE : View.VISIBLE);
- mClockViewBold.setVisibility(hasHeader ? View.VISIBLE : View.INVISIBLE);
- int paddingBottom = mContext.getResources().getDimensionPixelSize(hasHeader
- ? R.dimen.widget_vertical_padding_clock : R.dimen.title_clock_padding);
- mClockView.setPadding(mClockView.getPaddingLeft(), mClockView.getPaddingTop(),
- mClockView.getPaddingRight(), paddingBottom);
- mClockViewBold.setPadding(mClockViewBold.getPaddingLeft(), mClockViewBold.getPaddingTop(),
- mClockViewBold.getPaddingRight(), paddingBottom);
+ // End any current transitions before starting a new transition so that the new transition
+ // starts from a good state instead of a potentially bad intermediate state arrived at
+ // during a transition animation.
+ TransitionManager.endTransitions((ViewGroup) mClockView.getParent());
if (hasHeader) {
// After the transition, make the default clock GONE so that it doesn't make the
@@ -439,6 +435,16 @@ public class KeyguardClockSwitch extends RelativeLayout {
}
});
}
+
+ TransitionManager.beginDelayedTransition((ViewGroup) mClockView.getParent(), mTransition);
+ mClockView.setVisibility(hasHeader ? View.INVISIBLE : View.VISIBLE);
+ mClockViewBold.setVisibility(hasHeader ? View.VISIBLE : View.INVISIBLE);
+ int paddingBottom = mContext.getResources().getDimensionPixelSize(hasHeader
+ ? R.dimen.widget_vertical_padding_clock : R.dimen.title_clock_padding);
+ mClockView.setPadding(mClockView.getPaddingLeft(), mClockView.getPaddingTop(),
+ mClockView.getPaddingRight(), paddingBottom);
+ mClockViewBold.setPadding(mClockViewBold.getPaddingLeft(), mClockViewBold.getPaddingTop(),
+ mClockViewBold.getPaddingRight(), paddingBottom);
}
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
@@ -553,7 +559,6 @@ public class KeyguardClockSwitch extends RelativeLayout {
private Animator createAnimator(View view, float cutoff, int startVisibility,
int endVisibility, float startScale, float endScale) {
view.setPivotY(view.getHeight() - view.getPaddingBottom());
- view.setVisibility(startVisibility);
ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
animator.addUpdateListener(animation -> {
final float fraction = animation.getAnimatedFraction();
@@ -564,6 +569,14 @@ public class KeyguardClockSwitch extends RelativeLayout {
view.setScaleX(scale);
view.setScaleY(scale);
});
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ view.setVisibility(startVisibility);
+ animation.removeListener(this);
+ }
+ });
addListener(new TransitionListenerAdapter() {
@Override
public void onTransitionEnd(Transition transition) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index 0e91e4109ec0..d8086da277f2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -64,6 +64,9 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
// How much we scale up the duration of the disappear animation when the current user is locked
public static final float DISAPPEAR_MULTIPLIER_LOCKED = 1.5f;
+ // Extra padding, in pixels, that should eat touch events.
+ private static final int PATTERNS_TOUCH_AREA_EXTENSION = 40;
+
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final AppearAnimationUtils mAppearAnimationUtils;
private final DisappearAnimationUtils mDisappearAnimationUtils;
@@ -204,9 +207,10 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mLockPatternView.getLocationOnScreen(mTmpPosition);
- mLockPatternScreenBounds.set(mTmpPosition[0], mTmpPosition[1],
- mTmpPosition[0] + mLockPatternView.getWidth(),
- mTmpPosition[1] + mLockPatternView.getHeight());
+ mLockPatternScreenBounds.set(mTmpPosition[0] - PATTERNS_TOUCH_AREA_EXTENSION,
+ mTmpPosition[1] - PATTERNS_TOUCH_AREA_EXTENSION,
+ mTmpPosition[0] + mLockPatternView.getWidth() + PATTERNS_TOUCH_AREA_EXTENSION,
+ mTmpPosition[1] + mLockPatternView.getHeight() + PATTERNS_TOUCH_AREA_EXTENSION);
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 0914fb8330be..6cd971d25610 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -71,6 +71,8 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
private static final float TOUCH_Y_MULTIPLIER = 0.25f;
// How much you need to drag the bouncer to trigger an auth retry (in dps.)
private static final float MIN_DRAG_SIZE = 10;
+ // How much to scale the default slop by, to avoid accidental drags.
+ private static final float SLOP_SCALE = 2f;
private KeyguardSecurityModel mSecurityModel;
private LockPatternUtils mLockPatternUtils;
@@ -179,7 +181,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
return false;
}
int index = event.findPointerIndex(mActivePointerId);
- int touchSlop = mViewConfiguration.getScaledTouchSlop();
+ float touchSlop = mViewConfiguration.getScaledTouchSlop() * SLOP_SCALE;
if (mCurrentSecurityView != null && index != -1
&& mStartTouchY - event.getY(index) > touchSlop) {
mIsDragging = true;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 417cc68bb632..6a4dbc8d7228 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1187,7 +1187,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
throw new IllegalArgumentException("only handles intent ACTION_SIM_STATE_CHANGED");
}
String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
- int slotId = intent.getIntExtra(PhoneConstants.SLOT_KEY, 0);
+ int slotId = intent.getIntExtra(PhoneConstants.PHONE_KEY, 0);
int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index ed2a6b59d153..2be5743a84cd 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -16,13 +16,22 @@
package com.android.systemui;
+import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Rect;
-import android.opengl.GLSurfaceView;
import android.service.wallpaper.WallpaperService;
+import android.util.Log;
+import android.util.Size;
import android.view.SurfaceHolder;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.glwallpaper.EglHelper;
+import com.android.systemui.glwallpaper.GLWallpaperRenderer;
import com.android.systemui.glwallpaper.ImageWallpaperRenderer;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.phone.DozeParameters;
/**
* Default built-in wallpaper that simply shows a static image.
@@ -30,112 +39,183 @@ import com.android.systemui.glwallpaper.ImageWallpaperRenderer;
@SuppressWarnings({"UnusedDeclaration"})
public class ImageWallpaper extends WallpaperService {
private static final String TAG = ImageWallpaper.class.getSimpleName();
+ // We delayed destroy render context that subsequent render requests have chance to cancel it.
+ // This is to avoid destroying then recreating render context in a very short time.
+ private static final int DELAY_FINISH_RENDERING = 1000;
@Override
public Engine onCreateEngine() {
return new GLEngine(this);
}
- class GLEngine extends Engine {
- private GLWallpaperSurfaceView mWallpaperSurfaceView;
+ class GLEngine extends Engine implements GLWallpaperRenderer.SurfaceProxy, StateListener {
+ // Surface is rejected if size below a threshold on some devices (ie. 8px on elfin)
+ // set min to 64 px (CTS covers this), please refer to ag/4867989 for detail.
+ @VisibleForTesting
+ static final int MIN_SURFACE_WIDTH = 64;
+ @VisibleForTesting
+ static final int MIN_SURFACE_HEIGHT = 64;
+
+ private GLWallpaperRenderer mRenderer;
+ private EglHelper mEglHelper;
+ private StatusBarStateController mController;
+ private final Runnable mFinishRenderingTask = this::finishRendering;
+ private final boolean mNeedTransition;
+ private boolean mNeedRedraw;
GLEngine(Context context) {
- mWallpaperSurfaceView = new GLWallpaperSurfaceView(context);
- mWallpaperSurfaceView.setRenderer(
- new ImageWallpaperRenderer(context, mWallpaperSurfaceView));
- mWallpaperSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
- setOffsetNotificationsEnabled(true);
+ mNeedTransition = ActivityManager.isHighEndGfx()
+ && !DozeParameters.getInstance(context).getDisplayNeedsBlanking();
+
+ // We will preserve EGL context when we are in lock screen or aod
+ // to avoid janking in following transition, we need to release when back to home.
+ mController = Dependency.get(StatusBarStateController.class);
+ if (mController != null) {
+ mController.addCallback(this /* StateListener */);
+ }
+ mEglHelper = new EglHelper();
+ mRenderer = new ImageWallpaperRenderer(context, this /* SurfaceProxy */);
}
@Override
- public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) {
- if (mWallpaperSurfaceView != null) {
- mWallpaperSurfaceView.notifyAmbientModeChanged(inAmbientMode, animationDuration);
- }
+ public void onCreate(SurfaceHolder surfaceHolder) {
+ setFixedSizeAllowed(true);
+ setOffsetNotificationsEnabled(false);
+ updateSurfaceSize();
+ }
+
+ private void updateSurfaceSize() {
+ SurfaceHolder holder = getSurfaceHolder();
+ Size frameSize = mRenderer.reportSurfaceSize();
+ int width = Math.max(MIN_SURFACE_WIDTH, frameSize.getWidth());
+ int height = Math.max(MIN_SURFACE_HEIGHT, frameSize.getHeight());
+ holder.setFixedSize(width, height);
}
@Override
- public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep,
- float yOffsetStep, int xPixelOffset, int yPixelOffset) {
- if (mWallpaperSurfaceView != null) {
- mWallpaperSurfaceView.notifyOffsetsChanged(xOffset, yOffset);
- }
+ public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) {
+ mRenderer.updateAmbientMode(inAmbientMode,
+ (mNeedTransition || animationDuration != 0) ? animationDuration : 0);
}
@Override
public void onDestroy() {
- if (mWallpaperSurfaceView != null) {
- mWallpaperSurfaceView.onPause();
+ if (mController != null) {
+ mController.removeCallback(this /* StateListener */);
}
+ mController = null;
+ mRenderer.finish();
+ mRenderer = null;
+ mEglHelper.finish();
+ mEglHelper = null;
+ getSurfaceHolder().getSurface().hwuiDestroy();
}
- private class GLWallpaperSurfaceView extends GLSurfaceView implements ImageGLView {
- private WallpaperStatusListener mWallpaperStatusListener;
+ @Override
+ public void onSurfaceCreated(SurfaceHolder holder) {
+ mEglHelper.init(holder);
+ mRenderer.onSurfaceCreated();
+ }
- GLWallpaperSurfaceView(Context context) {
- super(context);
- setEGLContextClientVersion(2);
- }
+ @Override
+ public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ mRenderer.onSurfaceChanged(width, height);
+ mNeedRedraw = true;
+ }
- @Override
- public SurfaceHolder getHolder() {
- return getSurfaceHolder();
+ @Override
+ public void onSurfaceRedrawNeeded(SurfaceHolder holder) {
+ if (mNeedRedraw) {
+ preRender();
+ requestRender();
+ postRender();
+ mNeedRedraw = false;
}
+ }
- @Override
- public void setRenderer(Renderer renderer) {
- super.setRenderer(renderer);
- mWallpaperStatusListener = (WallpaperStatusListener) renderer;
+ @Override
+ public SurfaceHolder getHolder() {
+ return getSurfaceHolder();
+ }
+
+ @Override
+ public void onStatePostChange() {
+ // When back to home, we try to release EGL, which is preserved in lock screen or aod.
+ if (mController.getState() == StatusBarState.SHADE) {
+ scheduleFinishRendering();
}
+ }
- private void notifyAmbientModeChanged(boolean inAmbient, long duration) {
- if (mWallpaperStatusListener != null) {
- mWallpaperStatusListener.onAmbientModeChanged(inAmbient, duration);
+ @Override
+ public void preRender() {
+ boolean contextRecreated = false;
+ Rect frame = getSurfaceHolder().getSurfaceFrame();
+ getMainThreadHandler().removeCallbacks(mFinishRenderingTask);
+
+ // Check if we need to recreate egl context.
+ if (!mEglHelper.hasEglContext()) {
+ mEglHelper.destroyEglSurface();
+ if (!mEglHelper.createEglContext()) {
+ Log.w(TAG, "recreate egl context failed!");
+ } else {
+ contextRecreated = true;
}
}
- private void notifyOffsetsChanged(float xOffset, float yOffset) {
- if (mWallpaperStatusListener != null) {
- mWallpaperStatusListener.onOffsetsChanged(
- xOffset, yOffset, getHolder().getSurfaceFrame());
+ // Check if we need to recreate egl surface.
+ if (mEglHelper.hasEglContext() && !mEglHelper.hasEglSurface()) {
+ if (!mEglHelper.createEglSurface(getSurfaceHolder())) {
+ Log.w(TAG, "recreate egl surface failed!");
}
}
- @Override
- public void render() {
- requestRender();
+ // If we recreate egl context, notify renderer to setup again.
+ if (mEglHelper.hasEglContext() && mEglHelper.hasEglSurface() && contextRecreated) {
+ mRenderer.onSurfaceCreated();
+ mRenderer.onSurfaceChanged(frame.width(), frame.height());
}
}
- }
- /**
- * A listener to trace status of image wallpaper.
- */
- public interface WallpaperStatusListener {
-
- /**
- * Called back while ambient mode changes.
- * @param inAmbientMode true if is in ambient mode, false otherwise.
- * @param duration the duration of animation.
- */
- void onAmbientModeChanged(boolean inAmbientMode, long duration);
-
- /**
- * Called back while wallpaper offsets.
- * @param xOffset The offset portion along x.
- * @param yOffset The offset portion along y.
- */
- void onOffsetsChanged(float xOffset, float yOffset, Rect frame);
- }
+ @Override
+ public void requestRender() {
+ Rect frame = getSurfaceHolder().getSurfaceFrame();
+ boolean readyToRender = mEglHelper.hasEglContext() && mEglHelper.hasEglSurface()
+ && frame.width() > 0 && frame.height() > 0;
+
+ if (readyToRender) {
+ mRenderer.onDrawFrame();
+ if (!mEglHelper.swapBuffer()) {
+ Log.e(TAG, "drawFrame failed!");
+ }
+ } else {
+ Log.e(TAG, "requestRender: not ready, has context=" + mEglHelper.hasEglContext()
+ + ", has surface=" + mEglHelper.hasEglSurface()
+ + ", frame=" + frame);
+ }
+ }
- /**
- * An abstraction for view of GLRenderer.
- */
- public interface ImageGLView {
+ @Override
+ public void postRender() {
+ scheduleFinishRendering();
+ }
- /**
- * Ask the view to render.
- */
- void render();
+ private void scheduleFinishRendering() {
+ getMainThreadHandler().removeCallbacks(mFinishRenderingTask);
+ getMainThreadHandler().postDelayed(mFinishRenderingTask, DELAY_FINISH_RENDERING);
+ }
+
+ private void finishRendering() {
+ if (mEglHelper != null) {
+ mEglHelper.destroyEglSurface();
+ if (!needPreserveEglContext()) {
+ mEglHelper.destroyEglContext();
+ }
+ }
+ }
+
+ private boolean needPreserveEglContext() {
+ return mNeedTransition && mController != null
+ && mController.getState() == StatusBarState.KEYGUARD;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index c0f03a6f4ef8..69d3af8ff983 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -105,6 +105,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
private float mDensity;
private WindowManager mWindowManager;
private int mRotation;
+ private boolean mAssistHintVisible;
private DisplayCutoutView mCutoutTop;
private DisplayCutoutView mCutoutBottom;
private SecureSetting mColorInversionSetting;
@@ -133,6 +134,55 @@ public class ScreenDecorations extends SystemUI implements Tunable {
mHandler = startHandlerThread();
mHandler.post(this::startOnScreenDecorationsThread);
setupStatusBarPaddingIfNeeded();
+ putComponent(ScreenDecorations.class, this);
+ }
+
+ private void fade(View view, boolean fadeIn) {
+ if (fadeIn) {
+ view.animate().cancel();
+ view.setAlpha(0f);
+ view.setVisibility(View.VISIBLE);
+ view.animate().alpha(1f);
+ } else {
+ view.animate().cancel();
+ view.animate().alpha(0f).withEndAction(() -> view.setVisibility(View.INVISIBLE));
+ }
+
+ }
+
+ /**
+ * Controls the visibility of the assist gesture handles.
+ *
+ * @param visible whether the handles should be shown
+ */
+ public void setAssistHintVisible(boolean visible) {
+ if (mAssistHintVisible != visible) {
+ mAssistHintVisible = visible;
+
+ View assistHintTopLeft = mOverlay.findViewById(R.id.assist_hint_left);
+ View assistHintTopRight = mOverlay.findViewById(R.id.assist_hint_right);
+ View assistHintBottomLeft = mBottomOverlay.findViewById(R.id.assist_hint_left);
+ View assistHintBottomRight = mBottomOverlay.findViewById(R.id.assist_hint_right);
+
+ switch (mRotation) {
+ case RotationUtils.ROTATION_NONE:
+ fade(assistHintBottomLeft, mAssistHintVisible);
+ fade(assistHintBottomRight, mAssistHintVisible);
+ break;
+ case RotationUtils.ROTATION_LANDSCAPE:
+ fade(assistHintTopRight, mAssistHintVisible);
+ fade(assistHintBottomRight, mAssistHintVisible);
+ break;
+ case RotationUtils.ROTATION_SEASCAPE:
+ fade(assistHintTopLeft, mAssistHintVisible);
+ fade(assistHintBottomLeft, mAssistHintVisible);
+ break;
+ case RotationUtils.ROTATION_UPSIDE_DOWN:
+ fade(assistHintTopLeft, mAssistHintVisible);
+ fade(assistHintTopRight, mAssistHintVisible);
+ break;
+ }
+ }
}
@VisibleForTesting
@@ -375,12 +425,52 @@ public class ScreenDecorations extends SystemUI implements Tunable {
updateView(bottomRight, Gravity.TOP | Gravity.LEFT, 0);
}
+ updateAssistantHandleViews();
mCutoutTop.setRotation(mRotation);
mCutoutBottom.setRotation(mRotation);
updateWindowVisibilities();
}
+ private void updateAssistantHandleViews() {
+ View assistHintTopLeft = mOverlay.findViewById(R.id.assist_hint_left);
+ View assistHintTopRight = mOverlay.findViewById(R.id.assist_hint_right);
+ View assistHintBottomLeft = mBottomOverlay.findViewById(R.id.assist_hint_left);
+ View assistHintBottomRight = mBottomOverlay.findViewById(R.id.assist_hint_right);
+
+ final int assistHintVisibility = mAssistHintVisible ? View.VISIBLE : View.INVISIBLE;
+
+ if (mRotation == RotationUtils.ROTATION_NONE) {
+ assistHintTopLeft.setVisibility(View.GONE);
+ assistHintTopRight.setVisibility(View.GONE);
+ assistHintBottomLeft.setVisibility(assistHintVisibility);
+ assistHintBottomRight.setVisibility(assistHintVisibility);
+ updateView(assistHintBottomLeft, Gravity.BOTTOM | Gravity.LEFT, 270);
+ updateView(assistHintBottomRight, Gravity.BOTTOM | Gravity.RIGHT, 180);
+ } else if (mRotation == RotationUtils.ROTATION_LANDSCAPE) {
+ assistHintTopLeft.setVisibility(View.GONE);
+ assistHintTopRight.setVisibility(assistHintVisibility);
+ assistHintBottomLeft.setVisibility(View.GONE);
+ assistHintBottomRight.setVisibility(assistHintVisibility);
+ updateView(assistHintTopRight, Gravity.BOTTOM | Gravity.LEFT, 270);
+ updateView(assistHintBottomRight, Gravity.BOTTOM | Gravity.RIGHT, 180);
+ } else if (mRotation == RotationUtils.ROTATION_UPSIDE_DOWN) {
+ assistHintTopLeft.setVisibility(assistHintVisibility);
+ assistHintTopRight.setVisibility(assistHintVisibility);
+ assistHintBottomLeft.setVisibility(View.GONE);
+ assistHintBottomRight.setVisibility(View.GONE);
+ updateView(assistHintTopLeft, Gravity.BOTTOM | Gravity.LEFT, 270);
+ updateView(assistHintTopRight, Gravity.BOTTOM | Gravity.RIGHT, 180);
+ } else if (mRotation == RotationUtils.ROTATION_SEASCAPE) {
+ assistHintTopLeft.setVisibility(assistHintVisibility);
+ assistHintTopRight.setVisibility(View.GONE);
+ assistHintBottomLeft.setVisibility(assistHintVisibility);
+ assistHintBottomRight.setVisibility(View.GONE);
+ updateView(assistHintTopLeft, Gravity.BOTTOM | Gravity.RIGHT, 180);
+ updateView(assistHintBottomLeft, Gravity.BOTTOM | Gravity.LEFT, 270);
+ }
+ }
+
private void updateView(View v, int gravity, int rotation) {
((FrameLayout.LayoutParams)v.getLayoutParams()).gravity = gravity;
v.setRotation(rotation);
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index a3b2c95fa087..f0c38fb7534f 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -169,7 +169,7 @@ public class AssistManager implements ConfigurationChangedReceiver {
}
protected boolean shouldShowOrb() {
- return true;
+ return false;
}
public void startAssist(Bundle args) {
@@ -203,6 +203,14 @@ public class AssistManager implements ConfigurationChangedReceiver {
// intentional no-op, vendor's AssistManager implementation should override if needed.
}
+ /** Called when the user has invoked the assistant with the incoming velocity, in pixels per
+ * millisecond. For invocations without a velocity (e.g. slow drag), the velocity is set to
+ * zero.
+ */
+ public void onAssistantGestureCompletion(float velocity) {
+ // intentional no-op, vendor's AssistManager implementation should override if needed.
+ }
+
public void hideAssist() {
mAssistUtils.hideCurrentSession();
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java b/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java
index 8c070835f69e..ea08c335b31d 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java
@@ -136,7 +136,11 @@ final class PhoneStateMonitor {
}
private boolean isLauncherShowing(ActivityManager.RunningTaskInfo runningTaskInfo) {
- return runningTaskInfo.topActivity.equals(mDefaultHome);
+ if (runningTaskInfo == null) {
+ return false;
+ } else {
+ return runningTaskInfo.topActivity.equals(mDefaultHome);
+ }
}
private boolean isAppImmersive() {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index dcc0419ab0cf..7e016bb000ad 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -16,6 +16,7 @@
package com.android.systemui.bubbles;
+import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL;
import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL_ALL;
import static android.service.notification.NotificationListenerService.REASON_CANCEL;
@@ -41,7 +42,9 @@ import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
import android.app.Notification;
import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.content.pm.ParceledListSlice;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -112,7 +115,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
public static final int MAX_BUBBLES = 5; // TODO: actually enforce this
// Enables some subset of notifs to automatically become bubbles
- private static final boolean DEBUG_ENABLE_AUTO_BUBBLE = false;
+ public static final boolean DEBUG_ENABLE_AUTO_BUBBLE = false;
/** Flag to enable or disable the entire feature */
private static final String ENABLE_BUBBLES = "experiment_enable_bubbles";
@@ -450,7 +453,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
if (!areBubblesEnabled(mContext)) {
return;
}
- if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) {
+ if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)
+ && canLaunchInActivityView(mContext, entry)) {
updateShowInShadeForSuppressNotification(entry);
}
}
@@ -460,7 +464,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
if (!areBubblesEnabled(mContext)) {
return;
}
- if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) {
+ if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)
+ && canLaunchInActivityView(mContext, entry)) {
updateBubble(entry);
}
}
@@ -470,7 +475,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
if (!areBubblesEnabled(mContext)) {
return;
}
- boolean shouldBubble = mNotificationInterruptionStateProvider.shouldBubbleUp(entry);
+ boolean shouldBubble = mNotificationInterruptionStateProvider.shouldBubbleUp(entry)
+ && canLaunchInActivityView(mContext, entry);
if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.key)) {
// It was previously a bubble but no longer a bubble -- lets remove it
removeBubble(entry.key, DISMISS_NO_LONGER_BUBBLE);
@@ -657,12 +663,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
|| autoBubbleAll;
}
- private boolean shouldAutoExpand(NotificationEntry entry) {
- Notification.BubbleMetadata metadata = entry.getBubbleMetadata();
- return metadata != null && metadata.getAutoExpandBubble()
- && isForegroundApp(mContext, entry.notification.getPackageName());
- }
-
private void updateShowInShadeForSuppressNotification(NotificationEntry entry) {
boolean suppressNotification = entry.getBubbleMetadata() != null
&& entry.getBubbleMetadata().isNotificationSuppressed()
@@ -771,6 +771,48 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
(int) (defaultBounciness * 100)) / 100f;
}
+ /**
+ * Whether an intent is properly configured to display in an {@link android.app.ActivityView}.
+ *
+ * Keep checks in sync with NotificationManagerService#canLaunchInActivityView. Typically
+ * that should filter out any invalid bubbles, but should protect SysUI side just in case.
+ *
+ * @param context the context to use.
+ * @param entry the entry to bubble.
+ */
+ static boolean canLaunchInActivityView(Context context, NotificationEntry entry) {
+ PendingIntent intent = entry.getBubbleMetadata() != null
+ ? entry.getBubbleMetadata().getIntent()
+ : null;
+ if (intent == null) {
+ Log.w(TAG, "Unable to create bubble -- no intent");
+ return false;
+ }
+ ActivityInfo info =
+ intent.getIntent().resolveActivityInfo(context.getPackageManager(), 0);
+ if (info == null) {
+ Log.w(TAG, "Unable to send as bubble -- couldn't find activity info for intent: "
+ + intent);
+ return false;
+ }
+ if (!ActivityInfo.isResizeableMode(info.resizeMode)) {
+ Log.w(TAG, "Unable to send as bubble -- activity is not resizable for intent: "
+ + intent);
+ return false;
+ }
+ if (info.documentLaunchMode != DOCUMENT_LAUNCH_ALWAYS) {
+ Log.w(TAG, "Unable to send as bubble -- activity is not documentLaunchMode=always "
+ + "for intent: " + intent);
+ return false;
+ }
+ if ((info.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
+ Log.w(TAG, "Unable to send as bubble -- activity is not embeddable for intent: "
+ + intent);
+ return false;
+ }
+ return true;
+ }
+
/** PinnedStackListener that dispatches IME visibility updates to the stack. */
private class BubblesImeListener extends IPinnedStackListener.Stub {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index fa137a1f6207..6add4a483103 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -16,12 +16,10 @@
package com.android.systemui.bubbles;
-import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
-import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING;
-import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE;
-import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__DOCUMENT_LAUNCH_NOT_ALWAYS;
import static android.view.Display.INVALID_DISPLAY;
+import static com.android.systemui.bubbles.BubbleController.DEBUG_ENABLE_AUTO_BUBBLE;
+
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.ActivityView;
@@ -30,7 +28,6 @@ import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
@@ -52,6 +49,7 @@ import android.view.ViewGroup;
import android.view.WindowInsets;
import android.widget.LinearLayout;
+import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.recents.TriangleShape;
@@ -87,6 +85,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
private int mBubbleHeight;
private int mPointerWidth;
private int mPointerHeight;
+ private ShapeDrawable mPointerDrawable;
private NotificationEntry mEntry;
private PackageManager mPm;
@@ -170,16 +169,11 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
mPointerWidth = res.getDimensionPixelSize(R.dimen.bubble_pointer_width);
mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
- TypedArray ta = getContext().obtainStyledAttributes(
- new int[] {android.R.attr.colorBackgroundFloating});
- int bgColor = ta.getColor(0, Color.WHITE);
- ta.recycle();
-
- ShapeDrawable triangleDrawable = new ShapeDrawable(TriangleShape.create(
- mPointerWidth, mPointerHeight, false /* pointUp */));
- triangleDrawable.setTint(bgColor);
- mPointerView.setBackground(triangleDrawable);
+ mPointerDrawable = new ShapeDrawable(TriangleShape.create(
+ mPointerWidth, mPointerHeight, true /* pointUp */));
+ mPointerView.setBackground(mPointerDrawable);
+ mPointerView.setVisibility(GONE);
mSettingsIconHeight = getContext().getResources().getDimensionPixelSize(
R.dimen.bubble_expanded_header_height);
@@ -190,8 +184,16 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
true /* singleTaskInstance */);
addView(mActivityView);
- // Make sure pointer is below activity view
- bringChildToFront(mPointerView);
+ // Expanded stack layout, top to bottom:
+ // Expanded view container
+ // ==> bubble row
+ // ==> expanded view
+ // ==> activity view
+ // ==> manage button
+ bringChildToFront(mActivityView);
+ bringChildToFront(mSettingsIcon);
+
+ applyThemeAttrs();
setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> {
// Keep track of IME displaying because we should not make any adjustments that might
@@ -206,6 +208,23 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
});
}
+ void applyThemeAttrs() {
+ TypedArray ta = getContext().obtainStyledAttributes(R.styleable.BubbleExpandedView);
+ int bgColor = ta.getColor(
+ R.styleable.BubbleExpandedView_android_colorBackgroundFloating, Color.WHITE);
+ float cornerRadius = ta.getDimension(
+ R.styleable.BubbleExpandedView_android_dialogCornerRadius, 0);
+ ta.recycle();
+
+ // Update triangle color.
+ mPointerDrawable.setTint(bgColor);
+
+ // Update ActivityView cornerRadius
+ if (ScreenDecorationsUtils.supportsRoundedCornersOnWindows(mContext.getResources())) {
+ mActivityView.setCornerRadius(cornerRadius);
+ }
+ }
+
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
@@ -266,7 +285,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
if (mAppIcon == null) {
mAppIcon = mPm.getDefaultActivityIcon();
}
- updateTheme();
+ applyThemeAttrs();
showSettingsIcon();
updateExpandedView();
}
@@ -306,21 +325,6 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
}
}
- void updateTheme() {
- // Get new colors.
- TypedArray ta = mContext.obtainStyledAttributes(
- new int[]{android.R.attr.colorBackgroundFloating, android.R.attr.colorForeground});
- int backgroundColor = ta.getColor(0, Color.WHITE /* default */);
- int foregroundColor = ta.getColor(1, Color.BLACK /* default */);
- ta.recycle();
-
- // Update triangle color.
- ShapeDrawable triangleDrawable = new ShapeDrawable(
- TriangleShape.create(mPointerWidth, mPointerHeight, false /* pointUp */));
- triangleDrawable.setTint(backgroundColor);
- mPointerView.setBackground(triangleDrawable);
- }
-
private void updateExpandedView() {
mBubbleIntent = getBubbleIntent(mEntry);
if (mBubbleIntent != null) {
@@ -330,11 +334,10 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
mNotifRow = null;
}
mActivityView.setVisibility(VISIBLE);
- } else {
+ } else if (DEBUG_ENABLE_AUTO_BUBBLE) {
// Hide activity view if we had it previously
mActivityView.setVisibility(GONE);
mNotifRow = mEntry.getRow();
-
}
updateView();
}
@@ -406,7 +409,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
Intent intent = getSettingsIntent(mEntry.notification.getPackageName(),
mEntry.notification.getUid());
mStackView.collapseStack(() -> {
- mContext.startActivity(intent);
+ mContext.startActivityAsUser(intent, mEntry.notification.getUser());
logBubbleClickEvent(mEntry,
StatsLog.BUBBLE_UICHANGED__ACTION__HEADER_GO_TO_SETTINGS);
});
@@ -444,6 +447,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
// Adjust for the pointer size
x -= (mPointerView.getWidth() / 2f);
mPointerView.setTranslationX(x);
+ mPointerView.setVisibility(VISIBLE);
}
/**
@@ -524,59 +528,14 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
@Nullable
private PendingIntent getBubbleIntent(NotificationEntry entry) {
Notification notif = entry.notification.getNotification();
- String packageName = entry.notification.getPackageName();
Notification.BubbleMetadata data = notif.getBubbleMetadata();
- if (data != null && canLaunchInActivityView(data.getIntent(), true /* enableLogging */,
- packageName)) {
+ if (BubbleController.canLaunchInActivityView(mContext, entry) && data != null) {
return data.getIntent();
- } else if (BubbleController.shouldUseContentIntent(mContext)
- && canLaunchInActivityView(notif.contentIntent, false /* enableLogging */,
- packageName)) {
- return notif.contentIntent;
}
return null;
}
/**
- * Whether an intent is properly configured to display in an {@link android.app.ActivityView}.
- *
- * @param intent the pending intent of the bubble.
- * @param enableLogging whether bubble developer error should be logged.
- * @param packageName the notification package name for this bubble.
- * @return
- */
- private boolean canLaunchInActivityView(PendingIntent intent, boolean enableLogging,
- String packageName) {
- if (intent == null) {
- return false;
- }
- ActivityInfo info =
- intent.getIntent().resolveActivityInfo(mContext.getPackageManager(), 0);
- if (info == null) {
- if (enableLogging) {
- StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName,
- BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING);
- }
- return false;
- }
- if (!ActivityInfo.isResizeableMode(info.resizeMode)) {
- if (enableLogging) {
- StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName,
- BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE);
- }
- return false;
- }
- if (info.documentLaunchMode != DOCUMENT_LAUNCH_ALWAYS) {
- if (enableLogging) {
- StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName,
- BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__DOCUMENT_LAUNCH_NOT_ALWAYS);
- }
- return false;
- }
- return (info.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) != 0;
- }
-
- /**
* Listener that is notified when a bubble is blocked.
*/
public interface OnBubbleBlockedListener {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index d66e8c2a0aaa..bec90d2edad1 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -176,6 +176,7 @@ public class BubbleStackView extends FrameLayout {
private int mExpandedViewPadding;
private int mExpandedAnimateXDistance;
private int mExpandedAnimateYDistance;
+ private int mPointerHeight;
private int mStatusBarHeight;
private int mPipDismissHeight;
private int mImeOffset;
@@ -303,6 +304,8 @@ public class BubbleStackView extends FrameLayout {
res.getDimensionPixelSize(R.dimen.bubble_expanded_animate_x_distance);
mExpandedAnimateYDistance =
res.getDimensionPixelSize(R.dimen.bubble_expanded_animate_y_distance);
+ mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
+
mStatusBarHeight =
res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
mPipDismissHeight = mContext.getResources().getDimensionPixelSize(
@@ -451,7 +454,7 @@ public class BubbleStackView extends FrameLayout {
public void onThemeChanged() {
for (Bubble b: mBubbleData.getBubbles()) {
b.iconView.updateViews();
- b.expandedView.updateTheme();
+ b.expandedView.applyThemeAttrs();
}
}
@@ -1282,15 +1285,16 @@ public class BubbleStackView extends FrameLayout {
*/
int getMaxExpandedHeight() {
int expandedY = (int) mExpandedAnimationController.getExpandedY();
- return expandedY - getStatusBarHeight();
+ // PIP dismiss view uses FLAG_LAYOUT_IN_SCREEN so we need to subtract the bottom inset
+ int pipDismissHeight = mPipDismissHeight - getBottomInset();
+ return mDisplaySize.y - expandedY - mBubbleSize - pipDismissHeight;
}
/**
* Calculates the y position of the expanded view when it is expanded.
*/
float getYPositionForExpandedView() {
- return mExpandedAnimationController.getExpandedY()
- - mExpandedBubble.expandedView.getExpandedSize() - mBubblePadding;
+ return getStatusBarHeight() + mBubbleSize + mBubblePadding + mPointerHeight;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index 4674a1f20360..ae8043f86cdd 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -301,13 +301,11 @@ public class ExpandedAnimationController
return 0;
}
final WindowInsets insets = mLayout.getRootWindowInsets();
- int keyboardHeight = insets.getSystemWindowInsetBottom()
- - insets.getStableInsetBottom();
- float bottomInset = keyboardHeight > 0
- ? keyboardHeight
- : (mPipDismissHeight - insets.getStableInsetBottom());
- // Stable insets are excluded from display size, so we must subtract it
- return mDisplaySize.y - mBubbleSizePx - mBubblePaddingPx - bottomInset;
+ return mBubblePaddingPx + Math.max(
+ mStatusBarHeight,
+ insets.getDisplayCutout() != null
+ ? insets.getDisplayCutout().getSafeInsetTop()
+ : 0);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/chooser/ChooserHelper.java b/packages/SystemUI/src/com/android/systemui/chooser/ChooserHelper.java
index a7df6f1cfa67..6c1da4711fec 100644
--- a/packages/SystemUI/src/com/android/systemui/chooser/ChooserHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/chooser/ChooserHelper.java
@@ -21,6 +21,7 @@ import android.app.ActivityTaskManager;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.StrictMode;
/**
* When a target is chosen from the SystemUI Chooser activity, unpack its arguments and
@@ -40,7 +41,15 @@ public class ChooserHelper {
final boolean ignoreTargetSecurity =
thisIntent.getBooleanExtra(ActivityTaskManager.EXTRA_IGNORE_TARGET_SECURITY, false);
final int userId = thisIntent.getIntExtra(Intent.EXTRA_USER_ID, -1);
- activity.startActivityAsCaller(
- chosenIntent, options, permissionToken, ignoreTargetSecurity, userId);
+
+ // We're dispatching intents that might be coming from legacy apps, so
+ // (as in com.android.internal.app.ResolverActivity) exempt ourselves from death.
+ StrictMode.disableDeathOnFileUriExposure();
+ try {
+ activity.startActivityAsCaller(
+ chosenIntent, options, permissionToken, ignoreTargetSecurity, userId);
+ } finally {
+ StrictMode.enableDeathOnFileUriExposure();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 30f6e1affe0a..87d90adceba5 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -156,10 +156,7 @@ public class FragmentHostManager {
*/
protected void onConfigurationChanged(Configuration newConfig) {
if (mConfigChanges.applyNewConfig(mContext.getResources())) {
- // Save the old state.
- Parcelable p = destroyFragmentHost();
- // Generate a new fragment host and restore its state.
- createFragmentHost(p);
+ reloadFragments();
} else {
mFragments.dispatchConfigurationChanged(newConfig);
}
@@ -217,6 +214,13 @@ public class FragmentHostManager {
Dependency.get(FragmentService.class).removeAndDestroy(view);
}
+ public void reloadFragments() {
+ // Save the old state.
+ Parcelable p = destroyFragmentHost();
+ // Generate a new fragment host and restore its state.
+ createFragmentHost(p);
+ }
+
class HostCallbacks extends FragmentHostCallback<FragmentHostManager> {
public HostCallbacks() {
super(mContext, FragmentHostManager.this.mHandler, 0);
@@ -293,13 +297,6 @@ public class FragmentHostManager {
reloadFragments();
}
- private void reloadFragments() {
- // Save the old state.
- Parcelable p = destroyFragmentHost();
- // Generate a new fragment host and restore its state.
- createFragmentHost(p);
- }
-
Fragment instantiate(Context context, String className, Bundle arguments) {
Context extensionContext = mExtensionLookup.get(className);
if (extensionContext != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java
new file mode 100644
index 000000000000..b66cc4f83412
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.glwallpaper;
+
+import static android.opengl.EGL14.EGL_ALPHA_SIZE;
+import static android.opengl.EGL14.EGL_BLUE_SIZE;
+import static android.opengl.EGL14.EGL_CONFIG_CAVEAT;
+import static android.opengl.EGL14.EGL_CONTEXT_CLIENT_VERSION;
+import static android.opengl.EGL14.EGL_DEFAULT_DISPLAY;
+import static android.opengl.EGL14.EGL_DEPTH_SIZE;
+import static android.opengl.EGL14.EGL_GREEN_SIZE;
+import static android.opengl.EGL14.EGL_NONE;
+import static android.opengl.EGL14.EGL_NO_CONTEXT;
+import static android.opengl.EGL14.EGL_NO_DISPLAY;
+import static android.opengl.EGL14.EGL_NO_SURFACE;
+import static android.opengl.EGL14.EGL_OPENGL_ES2_BIT;
+import static android.opengl.EGL14.EGL_RED_SIZE;
+import static android.opengl.EGL14.EGL_RENDERABLE_TYPE;
+import static android.opengl.EGL14.EGL_STENCIL_SIZE;
+import static android.opengl.EGL14.EGL_SUCCESS;
+import static android.opengl.EGL14.eglChooseConfig;
+import static android.opengl.EGL14.eglCreateContext;
+import static android.opengl.EGL14.eglCreateWindowSurface;
+import static android.opengl.EGL14.eglDestroyContext;
+import static android.opengl.EGL14.eglDestroySurface;
+import static android.opengl.EGL14.eglGetDisplay;
+import static android.opengl.EGL14.eglGetError;
+import static android.opengl.EGL14.eglInitialize;
+import static android.opengl.EGL14.eglMakeCurrent;
+import static android.opengl.EGL14.eglSwapBuffers;
+import static android.opengl.EGL14.eglTerminate;
+
+import android.opengl.EGLConfig;
+import android.opengl.EGLContext;
+import android.opengl.EGLDisplay;
+import android.opengl.EGLSurface;
+import android.opengl.GLUtils;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+/**
+ * A helper class to handle EGL management.
+ */
+public class EglHelper {
+ private static final String TAG = EglHelper.class.getSimpleName();
+
+ private EGLDisplay mEglDisplay;
+ private EGLConfig mEglConfig;
+ private EGLContext mEglContext;
+ private EGLSurface mEglSurface;
+
+ /**
+ * Initialize EGL and prepare EglSurface.
+ * @param surfaceHolder surface holder.
+ * @return true if EglSurface is ready.
+ */
+ public boolean init(SurfaceHolder surfaceHolder) {
+ mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (mEglDisplay == EGL_NO_DISPLAY) {
+ Log.w(TAG, "eglGetDisplay failed: " + GLUtils.getEGLErrorString(eglGetError()));
+ return false;
+ }
+
+ if (!eglInitialize(mEglDisplay, null, 0, null, 0)) {
+ Log.w(TAG, "eglInitialize failed: " + GLUtils.getEGLErrorString(eglGetError()));
+ return false;
+ }
+
+ mEglConfig = chooseEglConfig();
+ if (mEglConfig == null) {
+ Log.w(TAG, "eglConfig not initialized!");
+ return false;
+ }
+
+ if (!createEglContext()) {
+ Log.w(TAG, "Can't create EGLContext!");
+ return false;
+ }
+
+ if (!createEglSurface(surfaceHolder)) {
+ Log.w(TAG, "Can't create EGLSurface!");
+ return false;
+ }
+
+ return true;
+ }
+
+ private EGLConfig chooseEglConfig() {
+ int[] configsCount = new int[1];
+ EGLConfig[] configs = new EGLConfig[1];
+ int[] configSpec = getConfig();
+ if (!eglChooseConfig(mEglDisplay, configSpec, 0, configs, 0, 1, configsCount, 0)) {
+ Log.w(TAG, "eglChooseConfig failed: " + GLUtils.getEGLErrorString(eglGetError()));
+ return null;
+ } else {
+ if (configsCount[0] <= 0) {
+ Log.w(TAG, "eglChooseConfig failed, invalid configs count: " + configsCount[0]);
+ return null;
+ } else {
+ return configs[0];
+ }
+ }
+ }
+
+ private int[] getConfig() {
+ return new int[] {
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_DEPTH_SIZE, 0,
+ EGL_STENCIL_SIZE, 0,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_CONFIG_CAVEAT, EGL_NONE,
+ EGL_NONE
+ };
+ }
+
+ /**
+ * Prepare an EglSurface.
+ * @param surfaceHolder surface holder.
+ * @return true if EglSurface is ready.
+ */
+ public boolean createEglSurface(SurfaceHolder surfaceHolder) {
+ mEglSurface = eglCreateWindowSurface(mEglDisplay, mEglConfig, surfaceHolder, null, 0);
+ if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
+ Log.w(TAG, "createWindowSurface failed: " + GLUtils.getEGLErrorString(eglGetError()));
+ return false;
+ }
+
+ if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
+ Log.w(TAG, "eglMakeCurrent failed: " + GLUtils.getEGLErrorString(eglGetError()));
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Destroy EglSurface.
+ */
+ public void destroyEglSurface() {
+ if (hasEglSurface()) {
+ eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroySurface(mEglDisplay, mEglSurface);
+ mEglSurface = null;
+ }
+ }
+
+ /**
+ * Check if we have a valid EglSurface.
+ * @return true if EglSurface is ready.
+ */
+ public boolean hasEglSurface() {
+ return mEglSurface != null && mEglSurface != EGL_NO_SURFACE;
+ }
+
+ /**
+ * Prepare EglContext.
+ * @return true if EglContext is ready.
+ */
+ public boolean createEglContext() {
+ int[] attrib_list = new int[] {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+ mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attrib_list, 0);
+ if (mEglContext == EGL_NO_CONTEXT) {
+ Log.w(TAG, "eglCreateContext failed: " + GLUtils.getEGLErrorString(eglGetError()));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Destroy EglContext.
+ */
+ public void destroyEglContext() {
+ if (hasEglContext()) {
+ eglDestroyContext(mEglDisplay, mEglContext);
+ mEglContext = null;
+ }
+ }
+
+ /**
+ * Check if we have EglContext.
+ * @return true if EglContext is ready.
+ */
+ public boolean hasEglContext() {
+ return mEglContext != null;
+ }
+
+ /**
+ * Swap buffer to display.
+ * @return true if swap successfully.
+ */
+ public boolean swapBuffer() {
+ boolean status = eglSwapBuffers(mEglDisplay, mEglSurface);
+ int error = eglGetError();
+ if (error != EGL_SUCCESS) {
+ Log.w(TAG, "eglSwapBuffers failed: " + GLUtils.getEGLErrorString(error));
+ }
+ return status;
+ }
+
+ /**
+ * Destroy EglSurface and EglContext, then terminate EGL.
+ */
+ public void finish() {
+ if (hasEglSurface()) {
+ destroyEglSurface();
+ }
+ if (hasEglContext()) {
+ destroyEglContext();
+ }
+ eglTerminate(mEglDisplay);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java
new file mode 100644
index 000000000000..8cc17b626946
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.glwallpaper;
+
+import android.util.Size;
+import android.view.SurfaceHolder;
+
+/**
+ * A renderer which is responsible for making OpenGL calls to render a frame.
+ */
+public interface GLWallpaperRenderer {
+
+ /**
+ * Called when the surface is created or recreated.
+ */
+ void onSurfaceCreated();
+
+ /**
+ * Called when the surface changed size.
+ * @param width surface width.
+ * @param height surface height.
+ */
+ void onSurfaceChanged(int width, int height);
+
+ /**
+ * Called to draw the current frame.
+ */
+ void onDrawFrame();
+
+ /**
+ * Notify ambient mode is changed.
+ * @param inAmbientMode true if in ambient mode.
+ * @param duration duration of transition.
+ */
+ void updateAmbientMode(boolean inAmbientMode, long duration);
+
+ /**
+ * Ask renderer to report the surface size it needs.
+ */
+ Size reportSurfaceSize();
+
+ /**
+ * Called when no need to render any more.
+ */
+ void finish();
+
+ /**
+ * A proxy which owns surface holder.
+ */
+ interface SurfaceProxy {
+
+ /**
+ * Get surface holder.
+ * @return surface holder.
+ */
+ SurfaceHolder getHolder();
+
+ /**
+ * Ask proxy to start rendering frame to surface.
+ */
+ void requestRender();
+
+ /**
+ * Ask proxy to prepare render context.
+ */
+ void preRender();
+
+ /**
+ * Ask proxy to destroy render context.
+ */
+ void postRender();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
index d935466757de..4be7623f90f2 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
@@ -195,76 +195,4 @@ class ImageGLWallpaper {
glUniform1i(mUniTexture, 0);
}
- /**
- * This method adjust s(x-axis), t(y-axis) texture coordinates
- * to prevent the wallpaper from being stretched.
- * The adjustment happens if either the width or height of the bitmap is larger than
- * corresponding size of the surface.
- * If both width and height are larger than corresponding size of the surface,
- * the adjustment will happen at both s, t side.
- *
- * @param bitmapWidth The width of the bitmap.
- * @param bitmapHeight The height of the bitmap.
- * @param surfaceWidth The width of the surface.
- * @param surfaceHeight The height of the surface.
- * @param xOffset The offset amount along s axis.
- * @param yOffset The offset amount along t axis.
- */
- void adjustTextureCoordinates(int bitmapWidth, int bitmapHeight,
- int surfaceWidth, int surfaceHeight, float xOffset, float yOffset) {
- float[] coordinates = TEXTURES.clone();
-
- if (bitmapWidth > surfaceWidth) {
- // Calculate the new s pos in pixels.
- float pixelS = (float) Math.round((bitmapWidth - surfaceWidth) * xOffset);
- // Calculate the s pos in texture coordinate.
- float coordinateS = pixelS / bitmapWidth;
- // Calculate the percentage occupied by the surface width in bitmap width.
- float surfacePercentageW = (float) surfaceWidth / bitmapWidth;
- // Need also consider the case if bitmap height is smaller than surface height.
- if (bitmapHeight < surfaceHeight) {
- // We will narrow the surface percentage to keep aspect ratio.
- surfacePercentageW *= (float) bitmapHeight / surfaceHeight;
- }
- // Determine the final s pos, also limit the legal s pos to prevent from out of range.
- float s = coordinateS + surfacePercentageW > 1f ? 1f - surfacePercentageW : coordinateS;
- // Traverse the s pos in texture coordinates array and adjust the s pos accordingly.
- for (int i = 0; i < coordinates.length; i += 2) {
- // indices 2, 4 and 6 are the end of s coordinates.
- if (i == 2 || i == 4 || i == 6) {
- coordinates[i] = Math.min(1f, s + surfacePercentageW);
- } else {
- coordinates[i] = s;
- }
- }
- }
-
- if (bitmapHeight > surfaceHeight) {
- // Calculate the new t pos in pixels.
- float pixelT = (float) Math.round((bitmapHeight - surfaceHeight) * yOffset);
- // Calculate the t pos in texture coordinate.
- float coordinateT = pixelT / bitmapHeight;
- // Calculate the percentage occupied by the surface height in bitmap height.
- float surfacePercentageH = (float) surfaceHeight / bitmapHeight;
- // Need also consider the case if bitmap width is smaller than surface width.
- if (bitmapWidth < surfaceWidth) {
- // We will narrow the surface percentage to keep aspect ratio.
- surfacePercentageH *= (float) bitmapWidth / surfaceWidth;
- }
- // Determine the final t pos, also limit the legal t pos to prevent from out of range.
- float t = coordinateT + surfacePercentageH > 1f ? 1f - surfacePercentageH : coordinateT;
- // Traverse the t pos in texture coordinates array and adjust the t pos accordingly.
- for (int i = 1; i < coordinates.length; i += 2) {
- // indices 1, 3 and 11 are the end of t coordinates.
- if (i == 1 || i == 3 || i == 11) {
- coordinates[i] = Math.min(1f, t + surfacePercentageH);
- } else {
- coordinates[i] = t;
- }
- }
- }
-
- mTextureBuffer.put(coordinates);
- mTextureBuffer.position(0);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
index 5914236ab349..6a1f24afe620 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
@@ -56,11 +56,18 @@ class ImageRevealHelper {
@Override
public void onAnimationEnd(Animator animation) {
- if (!mIsCanceled) {
- mAwake = !mAwake;
+ if (!mIsCanceled && mRevealListener != null) {
+ mRevealListener.onRevealEnd();
}
mIsCanceled = false;
}
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ if (mRevealListener != null) {
+ mRevealListener.onRevealStart();
+ }
+ }
});
}
@@ -74,10 +81,6 @@ class ImageRevealHelper {
return mReveal;
}
- public boolean isAwake() {
- return mAwake;
- }
-
void updateAwake(boolean awake, long duration) {
mAwake = awake;
mAnimator.setDuration(duration);
@@ -93,5 +96,15 @@ class ImageRevealHelper {
* Called back while reveal status changes.
*/
void onRevealStateChanged();
+
+ /**
+ * Called back while reveal starts.
+ */
+ void onRevealStart();
+
+ /**
+ * Called back while reveal ends.
+ */
+ void onRevealEnd();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
index 5bbfe84b6319..433e460ccfe8 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -26,23 +26,17 @@ import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Rect;
-import android.opengl.GLSurfaceView;
-import android.os.Build;
import android.util.Log;
import android.util.MathUtils;
+import android.util.Size;
-import com.android.systemui.ImageWallpaper;
-import com.android.systemui.ImageWallpaper.ImageGLView;
import com.android.systemui.R;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
/**
* A GL renderer for image wallpaper.
*/
-public class ImageWallpaperRenderer implements GLSurfaceView.Renderer,
- ImageWallpaper.WallpaperStatusListener, ImageRevealHelper.RevealStateListener {
+public class ImageWallpaperRenderer implements GLWallpaperRenderer,
+ ImageRevealHelper.RevealStateListener {
private static final String TAG = ImageWallpaperRenderer.class.getSimpleName();
private static final float SCALE_VIEWPORT_MIN = 0.98f;
private static final float SCALE_VIEWPORT_MAX = 1f;
@@ -52,62 +46,61 @@ public class ImageWallpaperRenderer implements GLSurfaceView.Renderer,
private final ImageGLWallpaper mWallpaper;
private final ImageProcessHelper mImageProcessHelper;
private final ImageRevealHelper mImageRevealHelper;
- private final ImageGLView mGLView;
- private float mXOffset = 0f;
- private float mYOffset = 0f;
- private int mWidth = 0;
- private int mHeight = 0;
+ private SurfaceProxy mProxy;
+ private Rect mSurfaceSize;
private Bitmap mBitmap;
- private int mBitmapWidth = 0;
- private int mBitmapHeight = 0;
- public ImageWallpaperRenderer(Context context, ImageGLView glView) {
+ public ImageWallpaperRenderer(Context context, SurfaceProxy proxy) {
mWallpaperManager = context.getSystemService(WallpaperManager.class);
if (mWallpaperManager == null) {
Log.w(TAG, "WallpaperManager not available");
}
+ mProxy = proxy;
mProgram = new ImageGLProgram(context);
mWallpaper = new ImageGLWallpaper(mProgram);
mImageProcessHelper = new ImageProcessHelper();
mImageRevealHelper = new ImageRevealHelper(this);
- mGLView = glView;
- if (mWallpaperManager != null) {
- mBitmap = mWallpaperManager.getBitmap();
- mBitmapWidth = mBitmap.getWidth();
- mBitmapHeight = mBitmap.getHeight();
+ if (loadBitmap()) {
// Compute threshold of the image, this is an async work.
mImageProcessHelper.start(mBitmap);
- mWallpaperManager.forgetLoadedWallpaper();
}
}
@Override
- public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ public void onSurfaceCreated() {
glClearColor(0f, 0f, 0f, 1.0f);
mProgram.useGLProgram(
R.raw.image_wallpaper_vertex_shader, R.raw.image_wallpaper_fragment_shader);
+
+ if (!loadBitmap()) {
+ Log.w(TAG, "reload bitmap failed!");
+ }
+
mWallpaper.setup(mBitmap);
mBitmap = null;
}
+ private boolean loadBitmap() {
+ if (mWallpaperManager != null && mBitmap == null) {
+ mBitmap = mWallpaperManager.getBitmap();
+ mWallpaperManager.forgetLoadedWallpaper();
+ if (mBitmap != null) {
+ mSurfaceSize = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
+ }
+ }
+ return mBitmap != null;
+ }
+
@Override
- public void onSurfaceChanged(GL10 gl, int width, int height) {
+ public void onSurfaceChanged(int width, int height) {
glViewport(0, 0, width, height);
- if (Build.IS_DEBUGGABLE) {
- Log.d(TAG, "onSurfaceChanged: width=" + width + ", height=" + height
- + ", xOffset=" + mXOffset + ", yOffset=" + mYOffset);
- }
- mWidth = width;
- mHeight = height;
- mWallpaper.adjustTextureCoordinates(
- mBitmapWidth, mBitmapHeight, width, height, mXOffset, mYOffset);
}
@Override
- public void onDrawFrame(GL10 gl) {
+ public void onDrawFrame() {
float threshold = mImageProcessHelper.getThreshold();
float reveal = mImageRevealHelper.getReveal();
@@ -122,50 +115,45 @@ public class ImageWallpaperRenderer implements GLSurfaceView.Renderer,
mWallpaper.draw();
}
+ @Override
+ public void updateAmbientMode(boolean inAmbientMode, long duration) {
+ mImageRevealHelper.updateAwake(!inAmbientMode, duration);
+ }
+
+ @Override
+ public Size reportSurfaceSize() {
+ return new Size(mSurfaceSize.width(), mSurfaceSize.height());
+ }
+
+ @Override
+ public void finish() {
+ mProxy = null;
+ }
+
private void scaleViewport(float reveal) {
+ int width = mSurfaceSize.width();
+ int height = mSurfaceSize.height();
// Interpolation between SCALE_VIEWPORT_MAX and SCALE_VIEWPORT_MIN by reveal.
float vpScaled = MathUtils.lerp(SCALE_VIEWPORT_MAX, SCALE_VIEWPORT_MIN, reveal);
// Calculate the offset amount from the lower left corner.
float offset = (SCALE_VIEWPORT_MAX - vpScaled) / 2;
// Change the viewport.
- glViewport((int) (mWidth * offset), (int) (mHeight * offset),
- (int) (mWidth * vpScaled), (int) (mHeight * vpScaled));
+ glViewport((int) (width * offset), (int) (height * offset),
+ (int) (width * vpScaled), (int) (height * vpScaled));
}
@Override
- public void onAmbientModeChanged(boolean inAmbientMode, long duration) {
- mImageRevealHelper.updateAwake(!inAmbientMode, duration);
- requestRender();
+ public void onRevealStateChanged() {
+ mProxy.requestRender();
}
@Override
- public void onOffsetsChanged(float xOffset, float yOffset, Rect frame) {
- if (frame == null || (xOffset == mXOffset && yOffset == mYOffset)) {
- return;
- }
-
- int width = frame.width();
- int height = frame.height();
- mXOffset = xOffset;
- mYOffset = yOffset;
-
- if (Build.IS_DEBUGGABLE) {
- Log.d(TAG, "onOffsetsChanged: width=" + width + ", height=" + height
- + ", xOffset=" + mXOffset + ", yOffset=" + mYOffset);
- }
- mWallpaper.adjustTextureCoordinates(
- mBitmapWidth, mBitmapHeight, width, height, mXOffset, mYOffset);
- requestRender();
+ public void onRevealStart() {
+ mProxy.preRender();
}
@Override
- public void onRevealStateChanged() {
- requestRender();
- }
-
- private void requestRender() {
- if (mGLView != null) {
- mGLView.render();
- }
+ public void onRevealEnd() {
+ mProxy.postRender();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index f6cd199f076e..4982dd49fecb 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -118,6 +118,8 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
private static final String SETTINGS_ACTION_OPEN_BATTERY_SAVER_SETTING =
"android.settings.BATTERY_SAVER_SETTINGS";
+ public static final String BATTERY_SAVER_SCHEDULE_SCREEN_INTENT_ACTION =
+ "com.android.settings.BATTERY_SAVER_SCHEDULE_SETTINGS";
private static final String BATTERY_SAVER_DESCRIPTION_URL_KEY = "url";
@@ -152,16 +154,18 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
private SystemUIDialog mThermalShutdownDialog;
@VisibleForTesting SystemUIDialog mUsbHighTempDialog;
private BatteryStateSnapshot mCurrentBatterySnapshot;
+ private ActivityStarter mActivityStarter;
/**
*/
@Inject
- public PowerNotificationWarnings(Context context) {
+ public PowerNotificationWarnings(Context context, ActivityStarter activityStarter) {
mContext = context;
mNoMan = mContext.getSystemService(NotificationManager.class);
mPowerMan = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mKeyguard = mContext.getSystemService(KeyguardManager.class);
mReceiver.init();
+ mActivityStarter = activityStarter;
}
@Override
@@ -172,7 +176,6 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
pw.print("mShowing="); pw.println(SHOWING_STRINGS[mShowing]);
pw.print("mSaverConfirmation="); pw.println(mSaverConfirmation != null ? "not null" : null);
pw.print("mSaverEnabledConfirmation=");
- pw.println(mSaverEnabledConfirmation != null ? "not null" : null);
pw.print("mHighTempWarning="); pw.println(mHighTempWarning);
pw.print("mHighTempDialog="); pw.println(mHighTempDialog != null ? "not null" : null);
pw.print("mThermalShutdownDialog=");
@@ -305,8 +308,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
.setWhen(0)
.setShowWhen(false)
.setContentTitle(mContext.getString(R.string.auto_saver_title))
- .setContentText(mContext.getString(R.string.auto_saver_text,
- getLowBatteryAutoTriggerDefaultLevel()));
+ .setContentText(mContext.getString(R.string.auto_saver_text));
nb.setContentIntent(pendingBroadcast(ACTION_ENABLE_AUTO_SAVER));
nb.setDeleteIntent(pendingBroadcast(ACTION_DISMISS_AUTO_SAVER_SUGGESTION));
nb.addAction(0,
@@ -673,51 +675,14 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
return builder;
}
- private void showAutoSaverEnabledConfirmation() {
- if (mSaverEnabledConfirmation != null) return;
-
- // Open the Battery Saver setting page.
- final Intent actionBatterySaverSetting =
- new Intent(SETTINGS_ACTION_OPEN_BATTERY_SAVER_SETTING)
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- final SystemUIDialog d = new SystemUIDialog(mContext);
- d.setTitle(R.string.auto_saver_enabled_title);
- d.setMessage(mContext.getString(R.string.auto_saver_enabled_text,
- getLowBatteryAutoTriggerDefaultLevel()));
-
- // "Got it". Just close the dialog. Automatic battery has been enabled already.
- d.setPositiveButton(R.string.auto_saver_okay_action,
- (dialog, which) -> onAutoSaverEnabledConfirmationClosed());
-
- // "Settings" -> Opens the battery saver settings activity.
- d.setNeutralButton(R.string.open_saver_setting_action, (dialog, which) -> {
- mContext.startActivity(actionBatterySaverSetting);
- onAutoSaverEnabledConfirmationClosed();
- });
- d.setShowForAllUsers(true);
- d.setOnDismissListener((dialog) -> onAutoSaverEnabledConfirmationClosed());
- d.show();
- mSaverEnabledConfirmation = d;
- }
-
- private void onAutoSaverEnabledConfirmationClosed() {
- mSaverEnabledConfirmation = null;
- }
-
private void setSaverMode(boolean mode, boolean needFirstTimeWarning) {
BatterySaverUtils.setPowerSaveMode(mContext, mode, needFirstTimeWarning);
}
- private void scheduleAutoBatterySaver() {
- int autoTriggerThreshold = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_lowBatteryWarningLevel);
- if (autoTriggerThreshold == 0) {
- autoTriggerThreshold = 15;
- }
-
- BatterySaverUtils.ensureAutoBatterySaver(mContext, autoTriggerThreshold);
- showAutoSaverEnabledConfirmation();
+ private void startBatterySaverSchedulePage() {
+ Intent intent = new Intent(BATTERY_SAVER_SCHEDULE_SCREEN_INTENT_ACTION);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ mActivityStarter.startActivity(intent, true /* dismissShade */);
}
private final class Receiver extends BroadcastReceiver {
@@ -771,7 +736,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
dismissAutoSaverSuggestion();
} else if (ACTION_ENABLE_AUTO_SAVER.equals(action)) {
dismissAutoSaverSuggestion();
- scheduleAutoBatterySaver();
+ startBatterySaverSchedulePage();
} else if (ACTION_AUTO_SAVER_NO_THANKS.equals(action)) {
dismissAutoSaverSuggestion();
BatterySaverUtils.suppressAutoBatterySaver(context);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHeaderInfoLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/QSHeaderInfoLayout.kt
new file mode 100644
index 000000000000..c65462193758
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSHeaderInfoLayout.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.qs
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.View
+import android.widget.FrameLayout
+import com.android.systemui.R
+
+/**
+ * Container for the Next Alarm and Ringer status texts in [QuickStatusBarHeader].
+ *
+ * If both elements are visible, it splits the available space according to the following rules:
+ * * If both views add up to less than the total space, they take all the space they need.
+ * * If both views are larger than half the space, each view takes half the space.
+ * * Otherwise, the smaller view takes the space it needs and the larger one takes all remaining
+ * space.
+ */
+class QSHeaderInfoLayout @JvmOverloads constructor(
+ context: Context,
+ attrs: AttributeSet? = null,
+ defStyle: Int = 0,
+ defStyleRes: Int = 0
+) : FrameLayout(context, attrs, defStyle, defStyleRes) {
+
+ private lateinit var alarmContainer: View
+ private lateinit var ringerContainer: View
+ private lateinit var statusSeparator: View
+ private val location = Location(0, 0)
+
+ override fun onFinishInflate() {
+ super.onFinishInflate()
+ alarmContainer = findViewById(R.id.alarm_container)
+ ringerContainer = findViewById(R.id.ringer_container)
+ statusSeparator = findViewById(R.id.status_separator)
+ }
+
+ override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
+ // At most one view is there
+ if (statusSeparator.visibility == View.GONE) super.onLayout(changed, l, t, r, b)
+ else {
+ val layoutRTL = isLayoutRtl
+ val width = r - l
+ val height = b - t
+ var offset = 0
+
+ offset += alarmContainer.layoutView(width, height, offset, layoutRTL)
+ offset += statusSeparator.layoutView(width, height, offset, layoutRTL)
+ ringerContainer.layoutView(width, height, offset, layoutRTL)
+ }
+ }
+
+ private fun View.layoutView(pWidth: Int, pHeight: Int, offset: Int, RTL: Boolean): Int {
+ location.setLocationFromOffset(pWidth, offset, this.measuredWidth, RTL)
+ layout(location.left, 0, location.right, pHeight)
+ return this.measuredWidth
+ }
+
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ super.onMeasure(
+ MeasureSpec.makeMeasureSpec(
+ MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST),
+ heightMeasureSpec)
+ val width = MeasureSpec.getSize(widthMeasureSpec)
+ // Once we measure the views, using as much space as they need, we need to remeasure them
+ // assigning them their final width. This is because TextViews decide whether to MARQUEE
+ // after onMeasure.
+ if (statusSeparator.visibility != View.GONE) {
+ val alarmWidth = alarmContainer.measuredWidth
+ val separatorWidth = statusSeparator.measuredWidth
+ val ringerWidth = ringerContainer.measuredWidth
+ val availableSpace = MeasureSpec.getSize(width) - separatorWidth
+ if (alarmWidth < availableSpace / 2) {
+ measureChild(
+ ringerContainer,
+ MeasureSpec.makeMeasureSpec(
+ Math.min(ringerWidth, availableSpace - alarmWidth),
+ MeasureSpec.AT_MOST),
+ heightMeasureSpec)
+ } else if (ringerWidth < availableSpace / 2) {
+ measureChild(alarmContainer,
+ MeasureSpec.makeMeasureSpec(
+ Math.min(alarmWidth, availableSpace - ringerWidth),
+ MeasureSpec.AT_MOST),
+ heightMeasureSpec)
+ } else {
+ measureChild(
+ alarmContainer,
+ MeasureSpec.makeMeasureSpec(availableSpace / 2, MeasureSpec.AT_MOST),
+ heightMeasureSpec)
+ measureChild(
+ ringerContainer,
+ MeasureSpec.makeMeasureSpec(availableSpace / 2, MeasureSpec.AT_MOST),
+ heightMeasureSpec)
+ }
+ }
+ setMeasuredDimension(width, measuredHeight)
+ }
+
+ private data class Location(var left: Int, var right: Int) {
+ /**
+ * Sets the [left] and [right] with the correct values for laying out the child, respecting
+ * RTL. Only set the variable through here to prevent concurrency issues.
+ * This is done to prevent allocation of [Pair] in [onLayout].
+ */
+ fun setLocationFromOffset(parentWidth: Int, offset: Int, width: Int, RTL: Boolean) {
+ if (RTL) {
+ left = parentWidth - offset - width
+ right = parentWidth - offset
+ } else {
+ left = offset
+ right = offset + width
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index ce3c04e6c6be..984274817fef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -321,6 +321,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements
}
mRingerModeIcon.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
mRingerModeTextView.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
+ mRingerContainer.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
return isOriginalVisible != ringerVisible ||
!Objects.equals(originalRingerText, mRingerModeTextView.getText());
@@ -337,6 +338,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements
}
mNextAlarmIcon.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
mNextAlarmTextView.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
+ mNextAlarmContainer.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
return isOriginalVisible != alarmVisible ||
!Objects.equals(originalAlarmText, mNextAlarmTextView.getText());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 1f857ff7b5ea..90455395db45 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -551,7 +551,7 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
mResId = resId;
}
- public static Icon get(int resId) {
+ public static synchronized Icon get(int resId) {
Icon icon = ICONS.get(resId);
if (icon == null) {
icon = new ResourceIcon(resId);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 51d259bbcd6f..1848219606db 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -27,9 +27,6 @@ import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INP
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SUPPORTS_WINDOW_CORNERS;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_WINDOW_CORNER_RADIUS;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
import android.annotation.FloatRange;
import android.app.ActivityTaskManager;
@@ -69,6 +66,7 @@ import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.phone.NavigationBarFragment;
+import com.android.systemui.statusbar.phone.NavigationBarView;
import com.android.systemui.statusbar.phone.NavigationModeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.CallbackController;
@@ -271,6 +269,19 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
}
@Override
+ public void onAssistantGestureCompletion(float velocity) {
+ if (!verifyCaller("onAssistantGestureCompletion")) {
+ return;
+ }
+ long token = Binder.clearCallingIdentity();
+ try {
+ mHandler.post(() -> notifyAssistantGestureCompletion(velocity));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
public void startAssistant(Bundle bundle) {
if (!verifyCaller("startAssistant")) {
return;
@@ -492,6 +503,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
}
if (mSysUiStateFlags != newState) {
mSysUiStateFlags = newState;
+ notifySystemUiStateChanged(mSysUiStateFlags);
notifySystemUiStateFlags(mSysUiStateFlags);
}
}
@@ -503,18 +515,19 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
private void updateSystemUiStateFlags() {
final NavigationBarController navBar = Dependency.get(NavigationBarController.class);
final NavigationBarFragment navBarFragment = navBar.getDefaultNavigationBarFragment();
+ final NavigationBarView navBarView = navBar.getNavigationBarView(mContext.getDisplayId());
final StatusBar statusBar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
- final boolean panelExpanded = statusBar != null && statusBar.getPanel() != null
- && statusBar.getPanel().isFullyExpanded();
- final boolean bouncerShowing = statusBar != null && statusBar.isBouncerShowing();
+
mSysUiStateFlags = 0;
- mSysUiStateFlags |= (navBarFragment != null && !navBarFragment.isNavBarWindowVisible())
- ? SYSUI_STATE_NAV_BAR_HIDDEN : 0;
- mSysUiStateFlags |= panelExpanded
- ? SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED : 0;
- mSysUiStateFlags |= bouncerShowing
- ? SYSUI_STATE_BOUNCER_SHOWING : 0;
- mSysUiStateFlags |= navBarFragment != null ? navBarFragment.getA11yButtonState(null) : 0;
+ if (navBarFragment != null) {
+ navBarFragment.updateSystemUiStateFlags(-1);
+ }
+ if (navBarView != null) {
+ navBarView.updateSystemUiStateFlags();
+ }
+ if (statusBar != null) {
+ statusBar.updateSystemUiStateFlags();
+ }
notifySystemUiStateFlags(mSysUiStateFlags);
}
@@ -620,6 +633,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
mConnectionCallbacks.add(listener);
listener.onConnectionChanged(mOverviewProxy != null);
listener.onBackButtonAlphaChanged(mBackButtonAlpha, false);
+ listener.onSystemUiStateChanged(mSysUiStateFlags);
}
@Override
@@ -684,6 +698,18 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
}
}
+ private void notifyAssistantGestureCompletion(float velocity) {
+ for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
+ mConnectionCallbacks.get(i).onAssistantGestureCompletion(velocity);
+ }
+ }
+
+ private void notifySystemUiStateChanged(int sysuiStateFlags) {
+ for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
+ mConnectionCallbacks.get(i).onSystemUiStateChanged(sysuiStateFlags);
+ }
+ }
+
private void notifyStartAssistant(Bundle bundle) {
for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
mConnectionCallbacks.get(i).startAssistant(bundle);
@@ -723,6 +749,11 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
pw.print(" quickStepIntent="); pw.println(mQuickStepIntent);
pw.print(" quickStepIntentResolved="); pw.println(isEnabled());
pw.print(" mSysUiStateFlags="); pw.println(mSysUiStateFlags);
+ pw.println(" " + QuickStepContract.getSystemUiStateString(mSysUiStateFlags));
+ pw.print(" backGestureDisabled=");
+ pw.println(QuickStepContract.isBackGestureDisabled(mSysUiStateFlags));
+ pw.print(" assistantGestureDisabled=");
+ pw.println(QuickStepContract.isAssistantGestureDisabled(mSysUiStateFlags));
}
public interface OverviewProxyListener {
@@ -731,7 +762,9 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
default void onOverviewShown(boolean fromHome) {}
default void onQuickScrubStarted() {}
default void onBackButtonAlphaChanged(float alpha, boolean animate) {}
+ default void onSystemUiStateChanged(int sysuiStateFlags) {}
default void onAssistantProgress(@FloatRange(from = 0.0, to = 1.0) float progress) {}
+ default void onAssistantGestureCompletion(float velocity) {}
default void startAssistant(Bundle bundle) {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index f97be1ea8358..6329af56077b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -115,6 +115,7 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
private static final int MSG_SHOW_CHARGING_ANIMATION = 44 << MSG_SHIFT;
private static final int MSG_SHOW_PINNING_TOAST_ENTER_EXIT = 45 << MSG_SHIFT;
private static final int MSG_SHOW_PINNING_TOAST_ESCAPE = 46 << MSG_SHIFT;
+ private static final int MSG_RECENTS_ANIMATION_STATE_CHANGED = 47 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -281,10 +282,16 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
* @see IStatusBar#onDisplayReady(int)
*/
default void onDisplayReady(int displayId) { }
+
/**
* @see DisplayManager.DisplayListener#onDisplayRemoved(int)
*/
default void onDisplayRemoved(int displayId) { }
+
+ /**
+ * @see IStatusBar#onRecentsAnimationStateChanged(boolean)
+ */
+ default void onRecentsAnimationStateChanged(boolean running) { }
}
@VisibleForTesting
@@ -785,6 +792,14 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
}
}
+ @Override
+ public void onRecentsAnimationStateChanged(boolean running) {
+ synchronized (mLock) {
+ mHandler.obtainMessage(MSG_RECENTS_ANIMATION_STATE_CHANGED, running ? 1 : 0, 0)
+ .sendToTarget();
+ }
+ }
+
private void handleShowImeButton(int displayId, IBinder token, int vis, int backDisposition,
boolean showImeSwitcher) {
if (displayId == INVALID_DISPLAY) return;
@@ -1071,6 +1086,11 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
mCallbacks.get(i).onDisplayReady(msg.arg1);
}
break;
+ case MSG_RECENTS_ANIMATION_STATE_CHANGED:
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).onRecentsAnimationStateChanged(msg.arg1 > 0);
+ }
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index d8070cdf53d5..5d4172dcc68a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -525,6 +525,7 @@ public class NotificationLockscreenUserManagerImpl implements
setLockscreenPublicMode(isProfilePublic, userId);
mUsersWithSeperateWorkChallenge.put(userId, needsSeparateChallenge);
}
+ getEntryManager().updateNotifications();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
index 812c9a7e9b8a..689d161c2ee8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarMobileView.java
@@ -212,7 +212,7 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver,
return;
}
mMobileDrawable.setTintList(
- ColorStateList.valueOf(mDualToneHandler.getFillColor(darkIntensity)));
+ ColorStateList.valueOf(mDualToneHandler.getSingleColor(darkIntensity)));
ColorStateList color = ColorStateList.valueOf(getTint(area, this, tint));
mIn.setImageTintList(color);
mOut.setImageTintList(color);
@@ -238,7 +238,7 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver,
// We want the ability to change the theme from the one set by SignalDrawable in certain
// surfaces. In this way, we can pass a theme to the view.
mMobileDrawable.setTintList(
- ColorStateList.valueOf(mDualToneHandler.getFillColor(intensity)));
+ ColorStateList.valueOf(mDualToneHandler.getSingleColor(intensity)));
mIn.setImageTintList(list);
mOut.setImageTintList(list);
mMobileType.setImageTintList(list);
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 942f56689170..e4e8c80867b1 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
@@ -94,6 +94,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
private static final int BUTTON_ANIM_TIME_MS = 200;
+ private static final boolean SHOW_BUTTON_SUMMARY = false;
+
private INotificationManager mINotificationManager;
private PackageManager mPm;
private MetricsLogger mMetricsLogger;
@@ -580,25 +582,27 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
transition.setDuration(BUTTON_ANIM_TIME_MS);
TransitionManager.beginDelayedTransition(this, transition);
}
- if (blockState == ACTION_ALERT) {
- TextView view = findViewById(R.id.alert_summary);
- view.setVisibility(VISIBLE);
- findViewById(R.id.silence_summary).setVisibility(GONE);
- view.setText(R.string.notification_channel_summary_default);
- } else {
- TextView view = findViewById(R.id.silence_summary);
- view.setVisibility(VISIBLE);
- findViewById(R.id.alert_summary).setVisibility(GONE);
- if (mShowInStatusBar) {
- if (mShowOnLockscreen) {
- view.setText(R.string.notification_channel_summary_low_status_lock);
+ if (SHOW_BUTTON_SUMMARY) {
+ if (blockState == ACTION_ALERT) {
+ TextView view = findViewById(R.id.alert_summary);
+ view.setVisibility(VISIBLE);
+ findViewById(R.id.silence_summary).setVisibility(GONE);
+ view.setText(R.string.notification_channel_summary_default);
+ } else {
+ TextView view = findViewById(R.id.silence_summary);
+ view.setVisibility(VISIBLE);
+ findViewById(R.id.alert_summary).setVisibility(GONE);
+ if (mShowInStatusBar) {
+ if (mShowOnLockscreen) {
+ view.setText(R.string.notification_channel_summary_low_status_lock);
+ } else {
+ view.setText(R.string.notification_channel_summary_low_status);
+ }
+ } else if (mShowOnLockscreen) {
+ view.setText(R.string.notification_channel_summary_low_lock);
} else {
- view.setText(R.string.notification_channel_summary_low_status);
+ view.setText(R.string.notification_channel_summary_low);
}
- } else if (mShowOnLockscreen) {
- view.setText(R.string.notification_channel_summary_low_lock);
- } else {
- view.setText(R.string.notification_channel_summary_low);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
index 82599f02ddf1..5747bb122fc4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
@@ -28,6 +28,8 @@ import android.view.View;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -40,18 +42,22 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvider {
private final NotificationStackScrollLayout mParent;
private final ActivityStarter mActivityStarter;
+ private final StatusBarStateController mStatusBarStateController;
private final boolean mUseMultipleSections;
private SectionHeaderView mGentleHeader;
private boolean mGentleHeaderVisible = false;
+ @Nullable private ExpandableNotificationRow mFirstGentleNotif;
@Nullable private View.OnClickListener mOnClearGentleNotifsClickListener;
NotificationSectionsManager(
NotificationStackScrollLayout parent,
ActivityStarter activityStarter,
+ StatusBarStateController statusBarStateController,
boolean useMultipleSections) {
mParent = parent;
mActivityStarter = activityStarter;
+ mStatusBarStateController = statusBarStateController;
mUseMultipleSections = useMultipleSections;
}
@@ -92,7 +98,7 @@ class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvide
@Override
public boolean beginsSection(View view) {
- return view == mGentleHeader;
+ return view == getFirstLowPriorityChild();
}
/**
@@ -104,6 +110,7 @@ class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvide
return;
}
+ mFirstGentleNotif = null;
int firstGentleNotifIndex = -1;
final int n = mParent.getChildCount();
@@ -114,6 +121,7 @@ class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvide
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
if (!row.getEntry().isHighPriority()) {
firstGentleNotifIndex = i;
+ mFirstGentleNotif = row;
break;
}
}
@@ -126,9 +134,12 @@ class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvide
}
private void adjustGentleHeaderVisibilityAndPosition(int firstGentleNotifIndex) {
+ final boolean showGentleHeader =
+ firstGentleNotifIndex != -1
+ && mStatusBarStateController.getState() != StatusBarState.KEYGUARD;
final int currentHeaderIndex = mParent.indexOfChild(mGentleHeader);
- if (firstGentleNotifIndex == -1) {
+ if (!showGentleHeader) {
if (mGentleHeaderVisible) {
mGentleHeaderVisible = false;
mParent.removeView(mGentleHeader);
@@ -208,7 +219,11 @@ class NotificationSectionsManager implements StackScrollAlgorithm.SectionProvide
@Nullable
private ActivatableNotificationView getFirstLowPriorityChild() {
- return mGentleHeaderVisible ? mGentleHeader : null;
+ if (mGentleHeaderVisible) {
+ return mGentleHeader;
+ } else {
+ return mFirstGentleNotif;
+ }
}
@Nullable
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 de187f1de1cc..8c73e9834195 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
@@ -409,7 +409,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
private final ViewOutlineProvider mOutlineProvider = new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
- if (mAmbientState.isDarkAtAll() || !mShowDarkShelf) {
+ if (mAmbientState.isDarkAtAll()) {
float xProgress = mDarkXInterpolator.getInterpolation(
(1 - mLinearDarkAmount) * mBackgroundXFactor);
outline.setRoundRect(mBackgroundAnimationRect,
@@ -507,7 +507,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
/**
* If the {@link NotificationShelf} should be visible when dark.
*/
- private boolean mShowDarkShelf;
private boolean mAnimateBottomOnLayout;
@Inject
@@ -518,7 +517,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
NotificationRoundnessManager notificationRoundnessManager,
AmbientPulseManager ambientPulseManager,
DynamicPrivacyController dynamicPrivacyController,
- ActivityStarter activityStarter) {
+ ActivityStarter activityStarter,
+ StatusBarStateController statusBarStateController) {
super(context, attrs, 0, 0);
Resources res = getResources();
@@ -534,6 +534,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
new NotificationSectionsManager(
this,
activityStarter,
+ statusBarStateController,
NotificationUtils.useNewInterruptionModel(context));
mSectionsManager.inflateViews(context);
mSectionsManager.setOnClearGentleNotifsClickListener(v -> {
@@ -913,7 +914,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
if (child.getVisibility() != View.GONE
&& child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
- if ((row.isPinned() || row.isHeadsUpAnimatingAway()) && row.getTranslation() < 0) {
+ if ((row.isPinned() || row.isHeadsUpAnimatingAway()) && row.getTranslation() < 0
+ && row.getProvider().shouldShowGutsOnSnapOpen()) {
top = Math.min(top, row.getTranslationY());
bottom = Math.max(bottom, row.getTranslationY() + row.getActualHeight());
}
@@ -1365,8 +1367,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
mIsClipped = clipped;
}
- if (!mAmbientPulseManager.hasNotifications()
- && mAmbientState.isFullyDark() && mShowDarkShelf) {
+ if (!mAmbientPulseManager.hasNotifications() && mAmbientState.isFullyDark()) {
setClipBounds(null);
} else if (mAmbientState.isDarkAtAll()) {
clipToOutline = true;
@@ -4378,6 +4379,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
mStackScrollAlgorithm.setIsExpanded(isExpanded);
mAmbientState.setShadeExpanded(isExpanded);
mStateAnimator.setShadeExpanded(isExpanded);
+ mSwipeHelper.setIsExpanded(isExpanded);
if (changed) {
if (!mIsExpanded) {
mGroupManager.collapseAllGroups();
@@ -4719,9 +4721,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
if (mAmbientState.isDark() == dark) {
return;
}
- if (!dark) {
- mShowDarkShelf = false;
- }
mAmbientState.setDark(dark);
if (animate && mAnimationsEnabled) {
mDarkNeedsAnimation = true;
@@ -4783,7 +4782,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
boolean nowDarkAtAll = mAmbientState.isDarkAtAll();
if (nowFullyDark != wasFullyDark) {
updateContentHeight();
- if (nowFullyDark && mShowDarkShelf) {
+ if (nowFullyDark) {
updateDarkShelfVisibility();
}
}
@@ -4799,14 +4798,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
requestChildrenUpdate();
}
- /**
- * If the shelf should be visible when the device is in ambient mode (dozing.)
- */
- @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void showDarkShelf() {
- mShowDarkShelf = true;
- }
-
private void updateDarkShelfVisibility() {
DozeParameters dozeParameters = DozeParameters.getInstance(mContext);
if (dozeParameters.shouldControlScreenOff()) {
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 4569b66d65f7..0f71192277df 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
@@ -48,6 +48,7 @@ class NotificationSwipeHelper extends SwipeHelper
private static final long SWIPE_MENU_TIMING = 200;
private NotificationMenuRowPlugin mCurrMenuRow;
+ private boolean mIsExpanded;
public NotificationSwipeHelper(int swipeDirection, NotificationCallback callback,
Context context, NotificationMenuRowPlugin.OnMenuEventListener menuListener) {
@@ -97,6 +98,10 @@ class NotificationSwipeHelper extends SwipeHelper
return mFalsingCheck;
}
+ public void setIsExpanded(boolean isExpanded) {
+ mIsExpanded = isExpanded;
+ }
+
@Override
protected void onChildSnappedBack(View animView, float targetLeft) {
if (mCurrMenuRow != null && targetLeft == 0) {
@@ -200,7 +205,9 @@ class NotificationSwipeHelper extends SwipeHelper
boolean slowSwipedFarEnough = swipedEnoughToShowMenu(menuRow) && isSlowSwipe;
boolean isFastNonDismissGesture =
gestureFastEnough && !gestureTowardsMenu && !isDismissGesture;
- boolean isMenuRevealingGestureAwayFromMenu = slowSwipedFarEnough || isFastNonDismissGesture;
+ boolean isAbleToShowMenu = menuRow.shouldShowGutsOnSnapOpen() || mIsExpanded;
+ boolean isMenuRevealingGestureAwayFromMenu = slowSwipedFarEnough
+ || (isFastNonDismissGesture && isAbleToShowMenu);
int menuSnapTarget = menuRow.getMenuSnapTarget();
boolean isNonFalseMenuRevealingGesture =
!isFalseGesture(ev) && isMenuRevealingGestureAwayFromMenu;
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 ce8463e70099..4d4818d51414 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -433,7 +433,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
public void onBiometricError(int msgId, String errString,
BiometricSourceType biometricSourceType) {
mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
- .setType(MetricsEvent.TYPE_ERROR).setSubtype(toSubtype(biometricSourceType)));
+ .setType(MetricsEvent.TYPE_ERROR).setSubtype(toSubtype(biometricSourceType))
+ .addTaggedData(MetricsEvent.FIELD_BIOMETRIC_AUTH_ERROR, msgId));
cleanup();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 4638c40c415d..f2218651d7c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -17,10 +17,6 @@ package com.android.systemui.statusbar.phone;
import static android.view.Display.INVALID_DISPLAY;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
-
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
@@ -125,8 +121,8 @@ public class EdgeBackGestureHandler implements DisplayListener {
private final int mEdgeWidth;
// The slop to distinguish between horizontal and vertical motion
private final float mTouchSlop;
- // Minimum distance to move so that is can be considerd as a back swipe
- private final float mSwipeThreshold;
+ // Duration after which we consider the event as longpress.
+ private final int mLongPressTimeout;
// The threshold where the touch needs to be at most, such that the arrow is displayed above the
// finger, otherwise it will be below
private final int mMinArrowPosition;
@@ -168,8 +164,9 @@ public class EdgeBackGestureHandler implements DisplayListener {
// TODO: Get this for the current user
mEdgeWidth = res.getDimensionPixelSize(
com.android.internal.R.dimen.config_backGestureInset);
+
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
- mSwipeThreshold = res.getDimension(R.dimen.navigation_edge_action_drag_threshold);
+ mLongPressTimeout = ViewConfiguration.getLongPressTimeout();
mNavBarHeight = res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height);
mMinArrowPosition = res.getDimensionPixelSize(
@@ -312,15 +309,23 @@ public class EdgeBackGestureHandler implements DisplayListener {
return !isInExcludedRegion;
}
+ private void cancelGesture(MotionEvent ev) {
+ // Send action cancel to reset all the touch events
+ mAllowGesture = false;
+ MotionEvent cancelEv = MotionEvent.obtain(ev);
+ cancelEv.setAction(MotionEvent.ACTION_CANCEL);
+ mEdgePanel.handleTouch(cancelEv);
+ cancelEv.recycle();
+ }
+
private void onMotionEvent(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ int action = ev.getActionMasked();
+ if (action == MotionEvent.ACTION_DOWN) {
// Verify if this is in within the touch region and we aren't in immersive mode, and
// either the bouncer is showing or the notification panel is hidden
int stateFlags = mOverviewProxyService.getSystemUiStateFlags();
mIsOnLeftEdge = ev.getX() <= mEdgeWidth;
- mAllowGesture = (stateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) == 0
- && ((stateFlags & SYSUI_STATE_BOUNCER_SHOWING) == SYSUI_STATE_BOUNCER_SHOWING
- || (stateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0)
+ mAllowGesture = !QuickStepContract.isBackGestureDisabled(stateFlags)
&& isWithinTouchRegion((int) ev.getX(), (int) ev.getY());
if (mAllowGesture) {
mEdgePanelLp.gravity = mIsOnLeftEdge
@@ -336,29 +341,35 @@ public class EdgeBackGestureHandler implements DisplayListener {
mThresholdCrossed = false;
}
} else if (mAllowGesture) {
- if (!mThresholdCrossed && ev.getAction() == MotionEvent.ACTION_MOVE) {
- float dx = Math.abs(ev.getX() - mDownPoint.x);
- float dy = Math.abs(ev.getY() - mDownPoint.y);
- if (dy > dx && dy > mTouchSlop) {
- // Send action cancel to reset all the touch events
- mAllowGesture = false;
- MotionEvent cancelEv = MotionEvent.obtain(ev);
- cancelEv.setAction(MotionEvent.ACTION_CANCEL);
- mEdgePanel.handleTouch(cancelEv);
- cancelEv.recycle();
+ if (!mThresholdCrossed) {
+ if (action == MotionEvent.ACTION_POINTER_DOWN) {
+ // We do not support multi touch for back gesture
+ cancelGesture(ev);
return;
-
- } else if (dx > dy && dx > mTouchSlop) {
- mThresholdCrossed = true;
- // Capture inputs
- mInputMonitor.pilferPointers();
+ } else if (action == MotionEvent.ACTION_MOVE) {
+ if ((ev.getEventTime() - ev.getDownTime()) > mLongPressTimeout) {
+ cancelGesture(ev);
+ return;
+ }
+ float dx = Math.abs(ev.getX() - mDownPoint.x);
+ float dy = Math.abs(ev.getY() - mDownPoint.y);
+ if (dy > dx && dy > mTouchSlop) {
+ cancelGesture(ev);
+ return;
+
+ } else if (dx > dy && dx > mTouchSlop) {
+ mThresholdCrossed = true;
+ // Capture inputs
+ mInputMonitor.pilferPointers();
+ }
}
+
}
// forward touch
mEdgePanel.handleTouch(ev);
- boolean isUp = ev.getAction() == MotionEvent.ACTION_UP;
+ boolean isUp = action == MotionEvent.ACTION_UP;
if (isUp) {
boolean performAction = mEdgePanel.shouldTriggerBack();
if (performAction) {
@@ -369,7 +380,7 @@ public class EdgeBackGestureHandler implements DisplayListener {
mOverviewProxyService.notifyBackAction(performAction, (int) mDownPoint.x,
(int) mDownPoint.y, false /* isButton */, !mIsOnLeftEdge);
}
- if (isUp || ev.getAction() == MotionEvent.ACTION_CANCEL) {
+ if (isUp || action == MotionEvent.ACTION_CANCEL) {
mRegionSamplingHelper.stop();
} else {
updateSamplingRect();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index b8887c4c90cd..61a394092761 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -95,6 +95,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
private boolean mWasPulsingOnThisFrame;
private boolean mWakeAndUnlockRunning;
private boolean mKeyguardShowing;
+ private boolean mShowingLaunchAffordance;
private final KeyguardMonitor.Callback mKeyguardMonitorCallback =
new KeyguardMonitor.Callback() {
@@ -299,7 +300,8 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
}
boolean onAodNotPulsingOrDocked = mDozing && (!mPulsing || mDocked);
- boolean invisible = onAodNotPulsingOrDocked || mWakeAndUnlockRunning;
+ boolean invisible = onAodNotPulsingOrDocked || mWakeAndUnlockRunning
+ || mShowingLaunchAffordance;
setVisibility(invisible ? INVISIBLE : VISIBLE);
updateClickability();
}
@@ -485,6 +487,14 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
}
/**
+ * When we're launching an affordance, like double pressing power to open camera.
+ */
+ public void onShowingLaunchAffordanceChanged(boolean showing) {
+ mShowingLaunchAffordance = showing;
+ update();
+ }
+
+ /**
* Called whenever the scrims become opaque, transparent or semi-transparent.
*/
public void onScrimVisibilityChanged(@ScrimVisibility int scrimsVisible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 1429718d5d9c..c9ba76c2be9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -329,8 +329,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
notifyNavigationBarScreenOn();
mOverviewProxyService.addCallback(mOverviewProxyListener);
- mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_NAV_BAR_HIDDEN,
- !isNavBarWindowVisible(), mDisplayId);
+ updateSystemUiStateFlags(-1);
// Currently there is no accelerometer sensor on non-default display.
if (mIsOnDefaultDisplay) {
@@ -458,8 +457,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
mNavigationBarWindowState = state;
if (DEBUG_WINDOW_STATE) Log.d(TAG, "Navigation bar " + windowStateToString(state));
- mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_NAV_BAR_HIDDEN,
- !isNavBarWindowVisible(), mDisplayId);
+ updateSystemUiStateFlags(-1);
mNavigationBarView.getRotateSuggestionButton()
.onNavigationBarWindowVisibilityChange(isNavBarWindowVisible());
}
@@ -576,7 +574,9 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
| StatusBarManager.DISABLE_SEARCH);
if (masked != mDisabledFlags1) {
mDisabledFlags1 = masked;
- if (mNavigationBarView != null) mNavigationBarView.setDisabledFlags(state1);
+ if (mNavigationBarView != null) {
+ mNavigationBarView.setDisabledFlags(state1);
+ }
updateScreenPinningGestures();
}
@@ -860,18 +860,30 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
private void updateAccessibilityServicesState(AccessibilityManager accessibilityManager) {
boolean[] feedbackEnabled = new boolean[1];
- int flags = getA11yButtonState(feedbackEnabled);
+ int a11yFlags = getA11yButtonState(feedbackEnabled);
mNavigationBarView.getRotateSuggestionButton()
.setAccessibilityFeedbackEnabled(feedbackEnabled[0]);
- boolean clickable = (flags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0;
- boolean longClickable = (flags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0;
+ boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0;
+ boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0;
mNavigationBarView.setAccessibilityButtonState(clickable, longClickable);
- mOverviewProxyService.setSystemUiStateFlag(
- SYSUI_STATE_A11Y_BUTTON_CLICKABLE, clickable, mDisplayId);
- mOverviewProxyService.setSystemUiStateFlag(
- SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE, longClickable, mDisplayId);
+
+ updateSystemUiStateFlags(a11yFlags);
+ }
+
+ public void updateSystemUiStateFlags(int a11yFlags) {
+ if (a11yFlags < 0) {
+ a11yFlags = getA11yButtonState(null);
+ }
+ boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0;
+ boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0;
+ mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_A11Y_BUTTON_CLICKABLE,
+ clickable, mDisplayId);
+ mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE,
+ longClickable, mDisplayId);
+ mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_NAV_BAR_HIDDEN,
+ !isNavBarWindowVisible(), mDisplayId);
}
/**
@@ -979,6 +991,17 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
public void onNavigationModeChanged(int mode) {
mNavBarMode = mode;
updateScreenPinningGestures();
+
+ // Workaround for b/132825155, for secondary users, we currently don't receive configuration
+ // changes on overlay package change since SystemUI runs for the system user. In this case,
+ // trigger a new configuration change to ensure that the nav bar is updated in the same way.
+ int userId = ActivityManagerWrapper.getInstance().getCurrentUserId();
+ if (userId != UserHandle.USER_SYSTEM) {
+ mHandler.post(() -> {
+ FragmentHostManager fragmentHost = FragmentHostManager.get(mNavigationBarView);
+ fragmentHost.reloadFragments();
+ });
+ }
}
public void disableAnimationsDuringHide(long delay) {
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 062fb6dcce92..5f619759d1ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -18,7 +18,10 @@ package com.android.systemui.statusbar.phone;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
import android.animation.LayoutTransition;
@@ -319,6 +322,7 @@ public class NavigationBarView extends FrameLayout implements
public void setComponents(NotificationPanelView panel, AssistManager assistManager) {
mPanelView = panel;
+ updateSystemUiStateFlags();
}
@Override
@@ -573,6 +577,7 @@ public class NavigationBarView extends FrameLayout implements
updateNavButtonIcons();
updateSlippery();
setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
+ updateSystemUiStateFlags();
}
public void updateNavButtonIcons() {
@@ -700,8 +705,21 @@ public class NavigationBarView extends FrameLayout implements
public void onPanelExpandedChange() {
updateSlippery();
- mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED,
- mPanelView.isFullyExpanded(), getContext().getDisplayId());
+ updateSystemUiStateFlags();
+ }
+
+ public void updateSystemUiStateFlags() {
+ int displayId = mContext.getDisplayId();
+ mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_SCREEN_PINNING,
+ ActivityManagerWrapper.getInstance().isScreenPinningActive(), displayId);
+ mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_OVERVIEW_DISABLED,
+ (mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0, displayId);
+ mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_HOME_DISABLED,
+ (mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0, displayId);
+ if (mPanelView != null) {
+ mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED,
+ mPanelView.isFullyExpanded() && !mPanelView.isInSettings(), displayId);
+ }
}
public void updateStates() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
index 6e5685459d6a..36050ac36016 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
@@ -17,12 +17,15 @@
package com.android.systemui.statusbar.phone;
import static android.content.Intent.ACTION_OVERLAY_CHANGED;
+import static android.content.Intent.ACTION_PREFERRED_ACTIVITY_CHANGED;
import static android.os.UserHandle.USER_CURRENT;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -56,7 +59,7 @@ import javax.inject.Singleton;
public class NavigationModeController implements Dumpable {
private static final String TAG = NavigationModeController.class.getSimpleName();
- private static final boolean DEBUG = true;
+ private static final boolean DEBUG = false;
public interface ModeChangedListener {
void onNavigationModeChanged(int mode);
@@ -76,11 +79,19 @@ public class NavigationModeController implements Dumpable {
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(ACTION_OVERLAY_CHANGED)) {
- if (DEBUG) {
- Log.d(TAG, "ACTION_OVERLAY_CHANGED");
- }
- updateCurrentInteractionMode(true /* notify */);
+ switch (intent.getAction()) {
+ case ACTION_OVERLAY_CHANGED:
+ if (DEBUG) {
+ Log.d(TAG, "ACTION_OVERLAY_CHANGED");
+ }
+ updateCurrentInteractionMode(true /* notify */);
+ break;
+ case ACTION_PREFERRED_ACTIVITY_CHANGED:
+ if (DEBUG) {
+ Log.d(TAG, "ACTION_PREFERRED_ACTIVITY_CHANGED");
+ }
+ switchFromGestureNavModeIfNotSupportedByDefaultLauncher();
+ break;
}
}
};
@@ -116,6 +127,7 @@ public class NavigationModeController implements Dumpable {
// Update the nav mode for the current user
updateCurrentInteractionMode(true /* notify */);
+ switchFromGestureNavModeIfNotSupportedByDefaultLauncher();
// When switching users, defer enabling the gestural nav overlay until the user
// is all set up
@@ -140,7 +152,12 @@ public class NavigationModeController implements Dumpable {
overlayFilter.addDataSchemeSpecificPart("android", PatternMatcher.PATTERN_LITERAL);
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, overlayFilter, null, null);
+ IntentFilter preferredActivityFilter = new IntentFilter(ACTION_PREFERRED_ACTIVITY_CHANGED);
+ mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, preferredActivityFilter, null,
+ null);
+
updateCurrentInteractionMode(false /* notify */);
+ switchFromGestureNavModeIfNotSupportedByDefaultLauncher();
// Check if we need to defer enabling gestural nav
deferGesturalNavOverlayIfNecessary();
@@ -175,6 +192,10 @@ public class NavigationModeController implements Dumpable {
private int getCurrentInteractionMode(Context context) {
int mode = context.getResources().getInteger(
com.android.internal.R.integer.config_navBarInteractionMode);
+ if (DEBUG) {
+ Log.d(TAG, "getCurrentInteractionMode: mode=" + mMode
+ + " contextUser=" + context.getUserId());
+ }
return mode;
}
@@ -250,6 +271,10 @@ public class NavigationModeController implements Dumpable {
mUiOffloadThread.submit(() -> {
try {
mOverlayManager.setEnabledExclusiveInCategory(overlayPkg, userId);
+ if (DEBUG) {
+ Log.d(TAG, "setModeOverlay: overlayPackage=" + overlayPkg
+ + " userId=" + userId);
+ }
} catch (RemoteException e) {
Log.e(TAG, "Failed to enable overlay " + overlayPkg + " for user " + userId);
}
@@ -277,4 +302,27 @@ public class NavigationModeController implements Dumpable {
Log.d(TAG, " " + a.getAssetPath());
}
}
+
+ private void switchFromGestureNavModeIfNotSupportedByDefaultLauncher() {
+ if (getCurrentInteractionMode(mCurrentUserContext) == NAV_BAR_MODE_GESTURAL
+ && !isGestureNavSupportedByDefaultLauncher(mCurrentUserContext)) {
+ setModeOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY, USER_CURRENT);
+ }
+ }
+
+ private boolean isGestureNavSupportedByDefaultLauncher(Context context) {
+ final ComponentName cn = context.getPackageManager().getHomeActivities(new ArrayList<>());
+ if (cn == null) {
+ // There is no default home app set for the current user, don't make any changes yet.
+ return true;
+ }
+ if (DEBUG) {
+ Log.d(TAG, "isGestureNavSupportedByDefaultLauncher: launcher=" + cn.getPackageName()
+ + " contextUser=" + context.getUserId());
+ }
+
+ ComponentName recentsComponentName = ComponentName.unflattenFromString(context.getString(
+ com.android.internal.R.string.config_recentsComponentName));
+ return recentsComponentName.getPackageName().equals(cn.getPackageName());
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index da9f2448a1aa..9da75b64acdf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -151,7 +151,8 @@ public class NotificationPanelView extends PanelView implements
private final NotificationWakeUpCoordinator mWakeUpCoordinator;
private final PulseExpansionHandler mPulseExpansionHandler;
- private KeyguardAffordanceHelper mAffordanceHelper;
+ @VisibleForTesting
+ protected KeyguardAffordanceHelper mAffordanceHelper;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
@VisibleForTesting
protected KeyguardStatusBarView mKeyguardStatusBar;
@@ -340,6 +341,7 @@ public class NotificationPanelView extends PanelView implements
*/
private int mThemeResId;
private KeyguardIndicationController mKeyguardIndicationController;
+ private Consumer<Boolean> mAffordanceLaunchListener;
@Inject
public NotificationPanelView(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
@@ -447,6 +449,14 @@ public class NotificationPanelView extends PanelView implements
R.dimen.qs_notification_padding);
}
+ /**
+ * @see #launchCamera(boolean, int)
+ * @see #setLaunchingAffordance(boolean)
+ */
+ public void setLaunchAffordanceListener(Consumer<Boolean> listener) {
+ mAffordanceLaunchListener = listener;
+ }
+
public void updateResources() {
Resources res = getResources();
int qsWidth = res.getDimensionPixelSize(R.dimen.qs_panel_width);
@@ -2743,6 +2753,9 @@ public class NotificationPanelView extends PanelView implements
private void setLaunchingAffordance(boolean launchingAffordance) {
getLeftIcon().setLaunchingAffordance(launchingAffordance);
getRightIcon().setLaunchingAffordance(launchingAffordance);
+ if (mAffordanceLaunchListener != null) {
+ mAffordanceLaunchListener.accept(launchingAffordance);
+ }
}
/**
@@ -2853,9 +2866,6 @@ public class NotificationPanelView extends PanelView implements
if (dozing == mDozing) return;
mDozing = dozing;
mNotificationStackScroller.setDark(mDozing, animate, wakeUpTouchLocation);
- if (mDozing) {
- mNotificationStackScroller.showDarkShelf();
- }
mKeyguardBottomArea.setDozing(mDozing, animate);
if (mBarState == StatusBarState.KEYGUARD
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index c6bbf7b43679..a9a3b2d866e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -1169,14 +1169,13 @@ public abstract class PanelView extends FrameLayout {
}
protected void notifyBarPanelExpansionChanged() {
- float fraction = mInstantExpanding ? 1 : mExpandedFraction;
if (mBar != null) {
- mBar.panelExpansionChanged(fraction, fraction > 0f
+ mBar.panelExpansionChanged(mExpandedFraction, mExpandedFraction > 0f
|| mPeekAnimator != null || mInstantExpanding
|| isPanelVisibleBecauseOfHeadsUp() || mTracking || mHeightAnimator != null);
}
if (mExpansionListener != null) {
- mExpansionListener.onPanelExpansionChanged(fraction, mTracking);
+ mExpansionListener.onPanelExpansionChanged(mExpandedFraction, mTracking);
}
}
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 3146595f3592..4e8f58413303 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -31,6 +31,7 @@ import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASL
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
import static com.android.systemui.shared.system.WindowManagerWrapper.NAV_BAR_POS_INVALID;
import static com.android.systemui.shared.system.WindowManagerWrapper.NAV_BAR_POS_LEFT;
import static com.android.systemui.statusbar.NotificationLockscreenUserManager.PERMISSION_SELF;
@@ -785,6 +786,7 @@ public class StatusBar extends SystemUI implements DemoMode,
Dependency.get(InitController.class).addPostInitTask(
() -> setUpDisableFlags(disabledFlags1, disabledFlags2));
+ updateSystemUiStateFlags();
}
// ================================================================================
@@ -949,6 +951,9 @@ public class StatusBar extends SystemUI implements DemoMode,
createUserSwitcher();
}
+ mNotificationPanel.setLaunchAffordanceListener(
+ mStatusBarWindow::onShowingLaunchAffordanceChanged);
+
// Set up the quick settings tile panel
View container = mStatusBarWindow.findViewById(R.id.qs_frame);
if (container != null) {
@@ -2156,6 +2161,11 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
+ @Override
+ public void onRecentsAnimationStateChanged(boolean running) {
+ setInteracting(StatusBarManager.WINDOW_NAVIGATION_BAR, running);
+ }
+
protected @TransitionMode int computeStatusBarMode(int oldVal, int newVal) {
return computeBarMode(oldVal, newVal);
}
@@ -3133,7 +3143,6 @@ public class StatusBar extends SystemUI implements DemoMode,
// If the state didn't change, we may still need to update public mode
mLockscreenUserManager.updatePublicMode();
- mEntryManager.updateNotifications();
}
if (mStatusBarStateController.leaveOpenOnKeyguardHide()) {
if (!mStatusBarStateController.isKeyguardRequested()) {
@@ -3412,6 +3421,7 @@ public class StatusBar extends SystemUI implements DemoMode,
updateDozingState();
checkBarModes();
updateScrimController();
+ updateSystemUiStateFlags();
mPresenter.updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
mKeyguardMonitor.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
mUnlockMethodCache.isMethodSecure(),
@@ -3578,10 +3588,16 @@ public class StatusBar extends SystemUI implements DemoMode,
if (!mBouncerShowing) {
updatePanelExpansionForKeyguard();
}
+ updateSystemUiStateFlags();
+ }
- // Notify overview proxy service of the new states
- Dependency.get(OverviewProxyService.class).setSystemUiStateFlag(SYSUI_STATE_BOUNCER_SHOWING,
- isBouncerShowing(), mContext.getDisplayId());
+ public void updateSystemUiStateFlags() {
+ OverviewProxyService overviewProxyService = Dependency.get(OverviewProxyService.class);
+ overviewProxyService.setSystemUiStateFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING,
+ mStatusBarStateController.getState() == StatusBarState.KEYGUARD,
+ mDisplayId);
+ overviewProxyService.setSystemUiStateFlag(SYSUI_STATE_BOUNCER_SHOWING,
+ isBouncerShowing(), mDisplayId);
}
/**
@@ -3623,6 +3639,7 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void onStartedGoingToSleep() {
+ updateNotificationPanelTouchState();
notifyHeadsUpGoingToSleep();
dismissVolumeDialog();
}
@@ -3655,7 +3672,10 @@ public class StatusBar extends SystemUI implements DemoMode,
* Keyguard.
*/
private void updateNotificationPanelTouchState() {
- mNotificationPanel.setTouchAndAnimationDisabled(!mDeviceInteractive && !mPulsing);
+ boolean goingToSleepWithoutAnimation = isGoingToSleep()
+ && !DozeParameters.getInstance(mContext).shouldControlScreenOff();
+ mNotificationPanel.setTouchAndAnimationDisabled((!mDeviceInteractive && !mPulsing)
+ || goingToSleepWithoutAnimation);
}
final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index 0865eb6ae7d2..6691f7a759f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -111,6 +111,7 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
}
protected void onWorkChallengeChanged() {
+ mLockscreenUserManager.updatePublicMode();
if (mPendingWorkRemoteInputView != null
&& !mLockscreenUserManager.isAnyProfilePublicMode()) {
// Expand notification panel and the notification row, then click on remote input view
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 049972ea0f43..7d5f23bc1e58 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -510,6 +510,15 @@ public class StatusBarWindowView extends FrameLayout {
}
}
+ /**
+ * When we're launching an affordance, like double pressing power to open camera.
+ */
+ public void onShowingLaunchAffordanceChanged(boolean showing) {
+ if (mLockIcon != null) {
+ mLockIcon.onShowingLaunchAffordanceChanged(showing);
+ }
+ }
+
public class LayoutParams extends FrameLayout.LayoutParams {
public boolean ignoreRightInset;
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 22006db47f19..d06164963f7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -378,8 +378,18 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
public int visibleState = STATE_ICON;
public boolean justAdded = true;
+ // How far we are from the end of the view actually is the most relevant for animation
+ float distanceToViewEnd = -1;
+
@Override
public void applyToView(View view) {
+ float parentWidth = 0;
+ if (view.getParent() instanceof View) {
+ parentWidth = ((View) view.getParent()).getWidth();
+ }
+
+ float currentDistanceToEnd = parentWidth - xTranslation;
+
if (!(view instanceof StatusIconDisplayable)) {
return;
}
@@ -403,7 +413,7 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
// all other transitions (to/from dot, etc)
animationProperties = ANIMATE_ALL_PROPERTIES;
}
- } else if (visibleState != STATE_HIDDEN && xTranslation != view.getTranslationX()) {
+ } else if (visibleState != STATE_HIDDEN && distanceToViewEnd != currentDistanceToEnd) {
// Visibility isn't changing, just animate position
animationProperties = X_ANIMATION_PROPERTIES;
}
@@ -416,6 +426,8 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
}
justAdded = false;
+ distanceToViewEnd = currentDistanceToEnd;
+
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbContaminantActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbContaminantActivity.java
index ecf608beb91c..aec14be9c39e 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbContaminantActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbContaminantActivity.java
@@ -16,30 +16,33 @@
package com.android.systemui.usb;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
+import android.app.Activity;
import android.content.Intent;
import android.hardware.usb.ParcelableUsbPort;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort;
import android.os.Bundle;
import android.util.Log;
+import android.view.View;
import android.view.Window;
import android.view.WindowManager;
+import android.widget.TextView;
import android.widget.Toast;
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
import com.android.systemui.R;
/**
* Activity that alerts the user when contaminant is detected on USB port.
*/
-public class UsbContaminantActivity extends AlertActivity
- implements DialogInterface.OnClickListener {
+public class UsbContaminantActivity extends Activity implements View.OnClickListener {
private static final String TAG = "UsbContaminantActivity";
private UsbPort mUsbPort;
+ private TextView mLearnMore;
+ private TextView mGotIt;
+ private TextView mEnableUsb;
+ private TextView mTitle;
+ private TextView mMessage;
@Override
public void onCreate(Bundle icicle) {
@@ -47,22 +50,30 @@ public class UsbContaminantActivity extends AlertActivity
window.addSystemFlags(WindowManager.LayoutParams
.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(icicle);
+ setContentView(R.layout.contaminant_dialog);
Intent intent = getIntent();
ParcelableUsbPort port = intent.getParcelableExtra(UsbManager.EXTRA_PORT);
mUsbPort = port.getUsbPort(getSystemService(UsbManager.class));
- final AlertController.AlertParams ap = mAlertParams;
- ap.mTitle = getString(R.string.usb_contaminant_title);
- ap.mMessage = getString(R.string.usb_contaminant_message);
- ap.mNegativeButtonText = getString(android.R.string.ok);
- ap.mNeutralButtonText = getString(R.string.usb_disable_contaminant_detection);
- ap.mNegativeButtonListener = this;
- ap.mNeutralButtonListener = this;
+ mLearnMore = findViewById(R.id.learnMore);
+ mEnableUsb = findViewById(R.id.enableUsb);
+ mGotIt = findViewById(R.id.gotIt);
+ mTitle = findViewById(R.id.title);
+ mMessage = findViewById(R.id.message);
- setupAlert();
+ mTitle.setText(getString(R.string.usb_contaminant_title));
+ mMessage.setText(getString(R.string.usb_contaminant_message));
+ mEnableUsb.setText(getString(R.string.usb_disable_contaminant_detection));
+ mGotIt.setText(getString(R.string.got_it));
+ mLearnMore.setText(getString(R.string.learn_more));
+
+ mEnableUsb.setOnClickListener(this);
+ mGotIt.setOnClickListener(this);
+ mLearnMore.setOnClickListener(this);
}
@Override
@@ -71,8 +82,8 @@ public class UsbContaminantActivity extends AlertActivity
}
@Override
- public void onClick(DialogInterface dialog, int which) {
- if (which == AlertDialog.BUTTON_NEUTRAL) {
+ public void onClick(View v) {
+ if (v == mEnableUsb) {
try {
mUsbPort.enableContaminantDetection(false);
Toast.makeText(this, R.string.usb_port_enabled,
@@ -80,6 +91,13 @@ public class UsbContaminantActivity extends AlertActivity
} catch (Exception e) {
Log.e(TAG, "Unable to notify Usb service", e);
}
+ } else if (v == mLearnMore) {
+ final Intent intent = new Intent();
+ intent.setClassName("com.android.settings",
+ "com.android.settings.HelpTrampoline");
+ intent.putExtra(Intent.EXTRA_TEXT,
+ "help_url_usb_contaminant_detected");
+ startActivity(intent);
}
finish();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
index a1c570785af7..74b15fb6f215 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
@@ -145,6 +145,7 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
}
@Test
+ @Ignore("Flaky")
public void testMagnetToDismiss_dismiss() throws InterruptedException {
expand();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
index 9d5c1a4ce79e..9218a8b93f66 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
@@ -158,6 +158,7 @@ public class StackAnimationControllerTest extends PhysicsAnimationLayoutTestCase
}
@Test
+ @Ignore("Flaking")
public void testChildAdded() throws InterruptedException {
// Move the stack to y = 500.
mStackController.moveFirstBubbleWithStackFollowing(0f, 500f);
@@ -233,6 +234,7 @@ public class StackAnimationControllerTest extends PhysicsAnimationLayoutTestCase
}
@Test
+ @Ignore("Flaky")
public void testMagnetToDismiss_dismiss() throws InterruptedException {
final Runnable after = Mockito.mock(Runnable.class);
@@ -252,6 +254,7 @@ public class StackAnimationControllerTest extends PhysicsAnimationLayoutTestCase
}
@Test
+ @Ignore("Flaking")
public void testMagnetToDismiss_demagnetizeThenDrag() throws InterruptedException {
final Runnable after = Mockito.mock(Runnable.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
index 58c931190c83..afb63ab0ebcf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
@@ -37,6 +37,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.util.NotificationChannels;
import org.junit.Before;
@@ -57,7 +58,8 @@ public class PowerNotificationWarningsTest extends SysuiTestCase {
public void setUp() throws Exception {
// Test Instance.
mContext.addMockSystemService(NotificationManager.class, mMockNotificationManager);
- mPowerNotificationWarnings = new PowerNotificationWarnings(mContext);
+ ActivityStarter starter = mDependency.injectMockDependency(ActivityStarter.class);
+ mPowerNotificationWarnings = new PowerNotificationWarnings(mContext, starter);
BatteryStateSnapshot snapshot = new BatteryStateSnapshot(100, false, false, 1,
BatteryManager.BATTERY_HEALTH_GOOD, 5, 15);
mPowerNotificationWarnings.updateSnapshot(snapshot);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/ResourceIconTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/ResourceIconTest.kt
new file mode 100644
index 000000000000..9c1cad62d1aa
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/ResourceIconTest.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tileimpl
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class ResourceIconTest : SysuiTestCase() {
+
+ val resIds = (1..1000).toList()
+
+ @Test
+ fun testMultipleThreadedPut() {
+ resIds.parallelStream().forEach {
+ QSTileImpl.ResourceIcon.get(it)
+ }
+ resIds.forEach {
+ assertEquals(it, (QSTileImpl.ResourceIcon.get(it) as QSTileImpl.ResourceIcon).mResId)
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index b049632942cf..84a7d4f0ff15 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -358,4 +358,11 @@ public class CommandQueueTest extends SysuiTestCase {
waitForIdleSync();
verify(mCallbacks).onDisplayRemoved(eq(SECONDARY_DISPLAY));
}
+
+ @Test
+ public void testOnRecentsAnimationStateChanged() {
+ mCommandQueue.onRecentsAnimationStateChanged(true);
+ waitForIdleSync();
+ verify(mCallbacks).onRecentsAnimationStateChanged(eq(true));
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
index 67c4a92bbb02..b99958a07ced 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
@@ -38,6 +38,8 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.ActivityStarterDelegate;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import org.junit.Before;
@@ -57,17 +59,24 @@ public class NotificationSectionsManagerTest extends SysuiTestCase {
@Mock private NotificationStackScrollLayout mNssl;
@Mock private ActivityStarterDelegate mActivityStarterDelegate;
+ @Mock private StatusBarStateController mStatusBarStateController;
private NotificationSectionsManager mSectionsManager;
@Before
public void setUp() {
- mSectionsManager = new NotificationSectionsManager(mNssl, mActivityStarterDelegate, true);
+ mSectionsManager =
+ new NotificationSectionsManager(
+ mNssl,
+ mActivityStarterDelegate,
+ mStatusBarStateController,
+ true);
// Required in order for the header inflation to work properly
when(mNssl.generateLayoutParams(any(AttributeSet.class)))
.thenReturn(new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
mSectionsManager.inflateViews(mContext);
when(mNssl.indexOfChild(any(View.class))).thenReturn(-1);
+ when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
}
@Test
@@ -185,6 +194,49 @@ public class NotificationSectionsManagerTest extends SysuiTestCase {
verify(mNssl).addView(mSectionsManager.getGentleHeaderView(), 1);
}
+ @Test
+ public void testHeaderNotShownOnLockscreen() {
+ // GIVEN a stack of HI and LO notifs on the lockscreen
+ when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
+ setStackState(ChildType.HIPRI, ChildType.HIPRI, ChildType.HIPRI, ChildType.LOPRI);
+
+ // WHEN we update the section headers
+ mSectionsManager.updateSectionBoundaries();
+
+ // Then the section header is not added
+ verify(mNssl, never()).addView(eq(mSectionsManager.getGentleHeaderView()), anyInt());
+ }
+
+ @Test
+ public void testHeaderShownWhenEnterLockscreen() {
+ // GIVEN a stack of HI and LO notifs on the lockscreen
+ when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
+ setStackState(ChildType.HIPRI, ChildType.HIPRI, ChildType.HIPRI, ChildType.LOPRI);
+ mSectionsManager.updateSectionBoundaries();
+
+ // WHEN we unlock
+ when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
+ mSectionsManager.updateSectionBoundaries();
+
+ // Then the section header is added
+ verify(mNssl).addView(mSectionsManager.getGentleHeaderView(), 3);
+ }
+
+ @Test
+ public void testHeaderHiddenWhenEnterLockscreen() {
+ // GIVEN a stack of HI and LO notifs on the shade
+ when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE_LOCKED);
+ setStackState(ChildType.HIPRI, ChildType.HIPRI, ChildType.HIPRI, ChildType.LOPRI);
+ mSectionsManager.updateSectionBoundaries();
+
+ // WHEN we go back to the keyguard
+ when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
+ mSectionsManager.updateSectionBoundaries();
+
+ // Then the section header is removed
+ verify(mNssl).removeView(eq(mSectionsManager.getGentleHeaderView()));
+ }
+
private enum ChildType { HEADER, HIPRI, LOPRI }
private void setStackState(ChildType... children) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 09b8062390bd..56265d08c131 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -153,7 +153,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
true /* allowLongPress */, mNotificationRoundnessManager,
new AmbientPulseManager(mContext),
mock(DynamicPrivacyController.class),
- mock(ActivityStarterDelegate.class));
+ mock(ActivityStarterDelegate.class),
+ mock(StatusBarStateController.class));
mStackScroller = spy(mStackScrollerInternal);
mStackScroller.setShelf(notificationShelf);
mStackScroller.setStatusBar(mBar);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 08471d8c1781..1b7ca952dbfe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -21,9 +21,11 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.StatusBarManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.MotionEvent;
@@ -36,6 +38,7 @@ import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.AmbientPulseManager;
+import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.PulseExpansionHandler;
@@ -55,6 +58,8 @@ import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.function.Consumer;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -90,6 +95,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
private HeadsUpTouchHelper.Callback mHeadsUpCallback;
@Mock
private PanelBar mPanelBar;
+ @Mock
+ private KeyguardAffordanceHelper mAffordanceHelper;
private NotificationPanelView mNotificationPanelView;
@Before
@@ -112,6 +119,9 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mNotificationPanelView = new TestableNotificationPanelView(coordinator, expansionHandler);
mNotificationPanelView.setHeadsUpManager(mHeadsUpManager);
mNotificationPanelView.setBar(mPanelBar);
+
+ when(mKeyguardBottomArea.getLeftView()).thenReturn(mock(KeyguardAffordanceView.class));
+ when(mKeyguardBottomArea.getRightView()).thenReturn(mock(KeyguardAffordanceView.class));
}
@Test
@@ -119,31 +129,29 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mNotificationPanelView.setDozing(true /* dozing */, true /* animate */, null /* touch */);
InOrder inOrder = inOrder(mNotificationStackScrollLayout, mStatusBarStateController);
inOrder.verify(mNotificationStackScrollLayout).setDark(eq(true), eq(true), eq(null));
- inOrder.verify(mNotificationStackScrollLayout).showDarkShelf();
inOrder.verify(mStatusBarStateController).setDozeAmount(eq(1f), eq(true));
}
@Test
- public void testSetDozing_showsDarkShelfWithDefaultClock() {
- when(mKeyguardStatusView.hasCustomClock()).thenReturn(false);
- mNotificationPanelView.setDozing(true /* dozing */, true /* animate */, null /* touch */);
- verify(mNotificationStackScrollLayout).showDarkShelf();
- }
-
- @Test
- public void testSetDozing_showsDarkShelfWhenCustomClock() {
- when(mKeyguardStatusView.hasCustomClock()).thenReturn(true);
- mNotificationPanelView.setDozing(true /* dozing */, true /* animate */, null /* touch */);
- verify(mNotificationStackScrollLayout).showDarkShelf();
- }
-
- @Test
public void testSetExpandedHeight() {
mNotificationPanelView.setExpandedHeight(200);
assertThat((int) mNotificationPanelView.getExpandedHeight()).isEqualTo(200);
}
@Test
+ public void testAffordanceLaunchingListener() {
+ Consumer<Boolean> listener = spy((showing) -> { });
+ mNotificationPanelView.setExpandedFraction(1f);
+ mNotificationPanelView.setLaunchAffordanceListener(listener);
+ mNotificationPanelView.launchCamera(false /* animate */,
+ StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP);
+ verify(listener).accept(eq(true));
+
+ mNotificationPanelView.onAffordanceLaunchEnded();
+ verify(listener).accept(eq(false));
+ }
+
+ @Test
public void testOnTouchEvent_expansionCanBeBlocked() {
mNotificationPanelView.onTouchEvent(MotionEvent.obtain(0L /* downTime */,
0L /* eventTime */, MotionEvent.ACTION_DOWN, 0f /* x */, 0f /* y */,
@@ -181,6 +189,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mKeyguardBottomArea = NotificationPanelViewTest.this.mKeyguardBottomArea;
mBigClockContainer = NotificationPanelViewTest.this.mBigClockContainer;
mQsFrame = NotificationPanelViewTest.this.mQsFrame;
+ mAffordanceHelper = NotificationPanelViewTest.this.mAffordanceHelper;
initDependencies(NotificationPanelViewTest.this.mStatusBar,
NotificationPanelViewTest.this.mGroupManager,
NotificationPanelViewTest.this.mNotificationShelf,
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-km/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-km/strings.xml
index fb0d88efb0ac..287817f9a8fa 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-km/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-km/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"សក់សេះនៅជ្រុង"</string>
+ <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"ក្បាលឆកនៅជ្រុង"</string>
</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-km/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-km/strings.xml
index 15535946f05b..312817f29cae 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-km/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-km/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"សក់សេះ​ភ្លោះ"</string>
+ <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"ក្បាលឆក​ភ្លោះ"</string>
</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-km/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-km/strings.xml
index 97e867f3f8f9..1fe37a7e179c 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-km/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-km/strings.xml
@@ -19,5 +19,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"សក់សេះ​តូច"</string>
+ <string name="display_cutout_emulation_overlay" msgid="3947428012427075896">"ក្បាលឆក​តូច"</string>
</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-km/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-km/strings.xml
index 5a01a6206111..38fc08c78af1 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-km/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-km/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"សក់សេះវែង"</string>
+ <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"ក្បាលឆកវែង"</string>
</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-km/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-km/strings.xml
index 7325a731fe88..3a720fd53d13 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-km/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-km/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"សក់សេះ​ធំ"</string>
+ <string name="display_cutout_emulation_overlay" msgid="4043478945358357737">"ក្បាលឆក​ធំ"</string>
</resources>
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index c59b16cf3e4c..71d03a86300d 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -7365,7 +7365,16 @@ message MetricsEvent {
// OS: Q
FIELD_EMERGENCY_DIALER_DISCONNECT_CAUSE = 1739;
- // ---- Skipping ahead to avoid conflicts between master and release branches.
+ // OPEN: Settings > Display > Dark Theme
+ // CATEGORY: SETTINGS
+ // OS: Q
+ // Note: Only shows up on first time toggle
+ DIALOG_DARK_UI_INFO = 1740;
+
+ // FIELD - Detailed reason in biometric authentication error.
+ // One of the constant value in BiometricConstants.java file.
+ // OS: Q
+ FIELD_BIOMETRIC_AUTH_ERROR = 1741;
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
diff --git a/services/art-profile b/services/art-profile
index cf0f13cec21b..a9d5982d0d90 100644
--- a/services/art-profile
+++ b/services/art-profile
@@ -13532,7 +13532,7 @@ HSPLcom/android/server/uri/UriGrantsManagerService;->checkHoldingPermissionsInte
HSPLcom/android/server/uri/UriGrantsManagerService;->checkUriPermission(Lcom/android/server/uri/GrantUri;II)Z
HSPLcom/android/server/uri/UriGrantsManagerService;->enforceNotIsolatedCaller(Ljava/lang/String;)V
HSPLcom/android/server/uri/UriGrantsManagerService;->findOrCreateUriPermission(Ljava/lang/String;Ljava/lang/String;ILcom/android/server/uri/GrantUri;)Lcom/android/server/uri/UriPermission;
-PLcom/android/server/uri/UriGrantsManagerService;->getPersistedUriPermissions(Ljava/lang/String;Z)Landroid/content/pm/ParceledListSlice;
+PLcom/android/server/uri/UriGrantsManagerService;->getPersistedUriPermissions(Ljava/lang/String;ZZ)Landroid/content/pm/ParceledListSlice;
HSPLcom/android/server/uri/UriGrantsManagerService;->getProviderInfo(Ljava/lang/String;II)Landroid/content/pm/ProviderInfo;
HSPLcom/android/server/uri/UriGrantsManagerService;->grantUriPermission(ILjava/lang/String;Lcom/android/server/uri/GrantUri;ILcom/android/server/uri/UriPermissionOwner;I)V
HSPLcom/android/server/uri/UriGrantsManagerService;->grantUriPermissionFromIntent(ILjava/lang/String;Landroid/content/Intent;Lcom/android/server/uri/UriPermissionOwner;I)V
diff --git a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
index d2b71e591b22..d42943ce76fe 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteAugmentedAutofillService.java
@@ -225,17 +225,7 @@ final class RemoteAugmentedAutofillService
@Override
public void cancel() {
- synchronized (mLock) {
- final boolean cancelled = isCancelledLocked();
- final ICancellationSignal cancellation = mCancellation;
- if (!cancelled) {
- try {
- cancellation.cancel();
- } catch (RemoteException e) {
- Slog.e(mTag, "Error requesting a cancellation", e);
- }
- }
- }
+ PendingAutofillRequest.this.cancel();
}
};
}
@@ -304,7 +294,7 @@ final class RemoteAugmentedAutofillService
try {
cancellation.cancel();
} catch (RemoteException e) {
- Slog.e(mTag, "Error cancelling a fill request", e);
+ Slog.e(mTag, "Error cancelling an augmented fill request", e);
}
}
return true;
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 9e1b3b8abc99..9855e4ea339a 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -51,8 +51,8 @@ java_library_static {
"android.hardware.configstore-V1.0-java",
"android.hardware.contexthub-V1.0-java",
"android.hidl.manager-V1.2-java",
- "dnsresolver_aidl_interface-java",
- "netd_aidl_interface-java",
+ "dnsresolver_aidl_interface-V2-java",
+ "netd_aidl_interface-V2-java",
"netd_event_listener_interface-java",
],
}
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index 9d979a6701c7..f92d0e0ff6f1 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -152,7 +152,18 @@ public class DynamicSystemService extends IDynamicSystemService.Stub implements
@Override
public boolean isInUse() throws RemoteException {
- return getGsiService().isGsiRunning();
+ boolean gsidWasRunning = "running".equals(SystemProperties.get("init.svc.gsid"));
+ boolean isInUse = false;
+
+ try {
+ isInUse = getGsiService().isGsiRunning();
+ } finally {
+ if (!gsidWasRunning && !isInUse) {
+ SystemProperties.set("ctl.stop", "gsid");
+ }
+ }
+
+ return isInUse;
}
@Override
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index fc355b7cce2f..bf56bc03b197 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -96,6 +96,7 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
+import android.os.UserManagerInternal;
import android.os.storage.DiskInfo;
import android.os.storage.IObbActionListener;
import android.os.storage.IStorageEventListener;
@@ -3242,7 +3243,22 @@ class StorageManagerService extends IStorageManager.Stub
public void opChanged(int op, int uid, String packageName) throws RemoteException {
if (!ENABLE_ISOLATED_STORAGE) return;
- remountUidExternalStorage(uid, getMountMode(uid, packageName));
+ if (op == OP_REQUEST_INSTALL_PACKAGES) {
+ // Only handling the case when the appop is denied. The other cases will be
+ // handled in the synchronous callback from AppOpsService.
+ if (packageName != null && mIAppOpsService.checkOperation(
+ OP_REQUEST_INSTALL_PACKAGES, uid, packageName) != MODE_ALLOWED) {
+ try {
+ ActivityManager.getService().killUid(
+ UserHandle.getAppId(uid), UserHandle.getUserId(uid),
+ "OP_REQUEST_INSTALL_PACKAGES is denied");
+ } catch (RemoteException e) {
+ // same process - should not happen
+ }
+ }
+ } else {
+ remountUidExternalStorage(uid, getMountMode(uid, packageName));
+ }
}
};
@@ -3579,8 +3595,14 @@ class StorageManagerService extends IStorageManager.Stub
if (Process.isIsolated(uid)) {
return Zygote.MOUNT_EXTERNAL_NONE;
}
+
+ final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid);
+ if (packageName == null) {
+ packageName = packagesForUid[0];
+ }
+
if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) {
- return Zygote.MOUNT_EXTERNAL_DEFAULT;
+ return Zygote.MOUNT_EXTERNAL_NONE;
}
// Determine if caller is holding runtime permission
@@ -3601,8 +3623,18 @@ class StorageManagerService extends IStorageManager.Stub
// runtime permission; this is a firm CDD requirement
final boolean hasInstall = mIPackageManager.checkUidPermission(INSTALL_PACKAGES,
uid) == PERMISSION_GRANTED;
- final boolean hasInstallOp = mIAppOpsService.checkOperation(OP_REQUEST_INSTALL_PACKAGES,
- uid, packageName) == MODE_ALLOWED;
+ boolean hasInstallOp = false;
+ // OP_REQUEST_INSTALL_PACKAGES is granted/denied per package but vold can't
+ // update mountpoints of a specific package. So, check the appop for all packages
+ // sharing the uid and allow same level of storage access for all packages even if
+ // one of the packages has the appop granted.
+ for (String uidPackageName : packagesForUid) {
+ if (mIAppOpsService.checkOperation(
+ OP_REQUEST_INSTALL_PACKAGES, uid, uidPackageName) == MODE_ALLOWED) {
+ hasInstallOp = true;
+ break;
+ }
+ }
if ((hasInstall || hasInstallOp) && hasWrite) {
return Zygote.MOUNT_EXTERNAL_WRITE;
}
@@ -3870,6 +3902,14 @@ class StorageManagerService extends IStorageManager.Stub
if (ENABLE_ISOLATED_STORAGE) {
return getMountMode(uid, packageName);
}
+ try {
+ if (packageName == null) {
+ final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid);
+ packageName = packagesForUid[0];
+ }
+ } catch (RemoteException e) {
+ // Should not happen - same process
+ }
// No locking - CopyOnWriteArrayList
int mountMode = Integer.MAX_VALUE;
for (ExternalStorageMountPolicy policy : mPolicies) {
@@ -3918,5 +3958,23 @@ class StorageManagerService extends IStorageManager.Stub
}
return true;
}
+
+ public void onAppOpsChanged(int code, int uid,
+ @Nullable String packageName, int mode) {
+ if (mode == MODE_ALLOWED && (code == OP_READ_EXTERNAL_STORAGE
+ || code == OP_WRITE_EXTERNAL_STORAGE
+ || code == OP_REQUEST_INSTALL_PACKAGES)) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ final UserManagerInternal userManagerInternal =
+ LocalServices.getService(UserManagerInternal.class);
+ if (userManagerInternal.isUserInitialized(UserHandle.getUserId(uid))) {
+ onExternalStoragePolicyChanged(uid, packageName);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/SystemServerInitThreadPool.java b/services/core/java/com/android/server/SystemServerInitThreadPool.java
index 1ce655618028..ff6a5375565a 100644
--- a/services/core/java/com/android/server/SystemServerInitThreadPool.java
+++ b/services/core/java/com/android/server/SystemServerInitThreadPool.java
@@ -45,7 +45,8 @@ public class SystemServerInitThreadPool {
private static SystemServerInitThreadPool sInstance;
- private ExecutorService mService = ConcurrentUtils.newFixedThreadPool(4,
+ private ExecutorService mService = ConcurrentUtils.newFixedThreadPool(
+ Runtime.getRuntime().availableProcessors(),
"system-server-init-thread", Process.THREAD_PRIORITY_FOREGROUND);
private List<String> mPendingTasks = new ArrayList<>();
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index a7fb99f8b004..e097d85293ab 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -617,9 +617,13 @@ public class Watchdog extends Thread {
// deadlock and the watchdog as a whole to be ineffective)
Thread dropboxThread = new Thread("watchdogWriteToDropbox") {
public void run() {
- mActivity.addErrorToDropBox(
- "watchdog", null, "system_server", null, null, null,
- subject, null, stack, null);
+ // If a watched thread hangs before init() is called, we don't have a
+ // valid mActivity. So we can't log the error to dropbox.
+ if (mActivity != null) {
+ mActivity.addErrorToDropBox(
+ "watchdog", null, "system_server", null, null, null,
+ subject, null, stack, null);
+ }
StatsLog.write(StatsLog.SYSTEM_SERVER_WATCHDOG_OCCURRED, subject);
}
};
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 0da39e7aee76..104cadca367e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -120,7 +120,7 @@ final class ActivityManagerConstants extends ContentObserver {
/**
* Default value for mFlagBackgroundActivityStartsEnabled if not explicitly set in
* Settings.Global. This allows it to be set experimentally unless it has been
- * enabled/disabled in developer options. Defaults to true.
+ * enabled/disabled in developer options. Defaults to false.
*/
private static final String KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED =
"default_background_activity_starts_enabled";
@@ -497,7 +497,7 @@ final class ActivityManagerConstants extends ContentObserver {
boolean enabledInDeviceConfig = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED,
- /*defaultValue*/ true);
+ /*defaultValue*/ false);
mFlagBackgroundActivityStartsEnabled = enabledInDeviceConfig;
if (!enabledInDeviceConfig) {
whitelistedPackageNames = DeviceConfig.getProperty(
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ea71a3b2e17e..a809d2194256 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -33,6 +33,7 @@ import static android.app.AppOpsManager.OP_NONE;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT;
import static android.content.pm.PackageManager.GET_PROVIDERS;
+import static android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES;
import static android.content.pm.PackageManager.MATCH_ALL;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
@@ -18566,6 +18567,21 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ /**
+ * Synchronously update the system ActivityThread, bypassing any deferred threading so any
+ * resources and overlaid values are available immediately.
+ */
+ public void updateSystemUiContext() {
+ PackageManagerInternal packageManagerInternal;
+ synchronized (this) {
+ packageManagerInternal = getPackageManagerInternalLocked();
+ }
+
+ ApplicationInfo ai = packageManagerInternal.getApplicationInfo("android",
+ GET_SHARED_LIBRARY_FILES, Binder.getCallingUid(), UserHandle.USER_SYSTEM);
+ ActivityThread.currentActivityThread().handleSystemApplicationInfoChanged(ai);
+ }
+
void updateApplicationInfoLocked(@NonNull List<String> packagesToUpdate, int userId) {
final boolean updateFrameworkRes = packagesToUpdate.contains("android");
if (updateFrameworkRes) {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 448e7738203a..0a7684553c08 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -1314,6 +1314,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
if (callbackSpecs == null) {
+ notifyOpChangedSync(code, uid, null, mode);
return;
}
@@ -1335,6 +1336,16 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
}
+
+ notifyOpChangedSync(code, uid, null, mode);
+ }
+
+ private void notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode) {
+ final StorageManagerInternal storageManagerInternal =
+ LocalServices.getService(StorageManagerInternal.class);
+ if (storageManagerInternal != null) {
+ storageManagerInternal.onAppOpsChanged(code, uid, packageName, mode);
+ }
}
/**
@@ -1438,6 +1449,8 @@ public class AppOpsService extends IAppOpsService.Stub {
AppOpsService::notifyOpChanged,
this, repCbs, code, uid, packageName));
}
+
+ notifyOpChangedSync(code, uid, packageName, mode);
}
private void notifyOpChanged(ArraySet<ModeCallback> callbacks, int code,
@@ -3801,8 +3814,9 @@ public class AppOpsService extends IAppOpsService.Stub {
if (mActiveWatchers.size() > 0 && dumpMode < 0) {
needSep = true;
boolean printedHeader = false;
- for (int i = 0; i < mActiveWatchers.size(); i++) {
- final SparseArray<ActiveCallback> activeWatchers = mActiveWatchers.valueAt(i);
+ for (int watcherNum = 0; watcherNum < mActiveWatchers.size(); watcherNum++) {
+ final SparseArray<ActiveCallback> activeWatchers =
+ mActiveWatchers.valueAt(watcherNum);
if (activeWatchers.size() <= 0) {
continue;
}
@@ -3820,16 +3834,16 @@ public class AppOpsService extends IAppOpsService.Stub {
}
pw.print(" ");
pw.print(Integer.toHexString(System.identityHashCode(
- mActiveWatchers.keyAt(i))));
+ mActiveWatchers.keyAt(watcherNum))));
pw.println(" ->");
pw.print(" [");
final int opCount = activeWatchers.size();
- for (i = 0; i < opCount; i++) {
- if (i > 0) {
+ for (int opNum = 0; opNum < opCount; opNum++) {
+ if (opNum > 0) {
pw.print(' ');
}
- pw.print(AppOpsManager.opToName(activeWatchers.keyAt(i)));
- if (i < opCount - 1) {
+ pw.print(AppOpsManager.opToName(activeWatchers.keyAt(opNum)));
+ if (opNum < opCount - 1) {
pw.print(',');
}
}
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index e14846863946..3b19d0875f5f 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -116,6 +116,14 @@ public class AttentionManagerService extends SystemService {
}
@Override
+ public void onBootPhase(int phase) {
+ if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+ mContext.registerReceiver(new ScreenStateReceiver(),
+ new IntentFilter(Intent.ACTION_SCREEN_OFF));
+ }
+ }
+
+ @Override
public void onStart() {
publishBinderService(Context.ATTENTION_SERVICE, new BinderService());
publishLocalService(AttentionManagerInternal.class, new LocalService());
@@ -135,10 +143,6 @@ public class AttentionManagerService extends SystemService {
private boolean isServiceAvailable() {
if (mComponentName == null) {
mComponentName = resolveAttentionService(mContext);
- if (mComponentName != null) {
- mContext.registerReceiver(new ScreenStateReceiver(),
- new IntentFilter(Intent.ACTION_SCREEN_OFF));
- }
}
return mComponentName != null;
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 4cde931d2ef5..15e8851a6a2b 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1452,7 +1452,13 @@ public class AudioService extends IAudioService.Stub
Settings.Secure.ASSISTANT, UserHandle.USER_CURRENT);
}
if (!TextUtils.isEmpty(assistantName)) {
- packageName = ComponentName.unflattenFromString(assistantName).getPackageName();
+ ComponentName componentName = ComponentName.unflattenFromString(assistantName);
+ if (componentName == null) {
+ Slog.w(TAG, "Invalid service name for "
+ + Settings.Secure.VOICE_INTERACTION_SERVICE + ": " + assistantName);
+ return;
+ }
+ packageName = componentName.getPackageName();
}
}
if (!TextUtils.isEmpty(packageName)) {
@@ -6698,7 +6704,10 @@ public class AudioService extends IAudioService.Stub
boolean isVolumeController, IMediaProjection projection) {
AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback);
- if (!isPolicyRegisterAllowed(policyConfig, projection)) {
+ if (!isPolicyRegisterAllowed(policyConfig,
+ isFocusPolicy || isTestFocusPolicy || hasFocusListener,
+ isVolumeController,
+ projection)) {
Slog.w(TAG, "Permission denied to register audio policy for pid "
+ Binder.getCallingPid() + " / uid " + Binder.getCallingUid()
+ ", need MODIFY_AUDIO_ROUTING or MediaProjection that can project audio");
@@ -6739,42 +6748,71 @@ public class AudioService extends IAudioService.Stub
* as those policy do not modify the audio routing.
*/
private boolean isPolicyRegisterAllowed(AudioPolicyConfig policyConfig,
- IMediaProjection projection) {
-
- boolean isLoopbackRenderPolicy = policyConfig.getMixes().stream().allMatch(
- mix -> mix.getRouteFlags() == (mix.ROUTE_FLAG_RENDER | mix.ROUTE_FLAG_LOOP_BACK));
-
- if (isLoopbackRenderPolicy) {
- boolean allowPrivilegedPlaybackCapture = policyConfig.getMixes().stream().anyMatch(
- mix -> mix.getRule().allowPrivilegedPlaybackCapture());
- if (allowPrivilegedPlaybackCapture
- && !(hasPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT)
- || hasPermission(android.Manifest.permission.CAPTURE_MEDIA_OUTPUT))) {
- // Opt-out can not be bypassed without a system permission
- return false;
+ boolean hasFocusAccess,
+ boolean isVolumeController,
+ IMediaProjection projection) {
+
+ boolean requireValidProjection = false;
+ boolean requireCaptureAudioOrMediaOutputPerm = false;
+ boolean requireModifyRouting = false;
+
+ if (hasFocusAccess || isVolumeController) {
+ requireModifyRouting |= true;
+ } else if (policyConfig.getMixes().isEmpty()) {
+ // An empty policy could be used to lock the focus or add mixes later
+ requireModifyRouting |= true;
+ }
+ for (AudioMix mix : policyConfig.getMixes()) {
+ // If mix is requesting a privileged capture
+ if (mix.getRule().allowPrivilegedPlaybackCapture()) {
+ // then it must have CAPTURE_MEDIA_OUTPUT or CAPTURE_AUDIO_OUTPUT permission
+ requireCaptureAudioOrMediaOutputPerm |= true;
+ // and its format must be low quality enough
+ String error = mix.canBeUsedForPrivilegedCapture(mix.getFormat());
+ if (error != null) {
+ Log.e(TAG, error);
+ return false;
+ }
}
- if (canProjectAudio(projection)) {
- // Policy that do not modify the audio routing only need an audio projection
- return true;
+ // If mix is RENDER|LOOPBACK, then an audio MediaProjection is enough
+ // otherwise MODIFY_AUDIO_ROUTING permission is required
+ if (mix.getRouteFlags() == mix.ROUTE_FLAG_LOOP_BACK_RENDER && projection != null) {
+ requireValidProjection |= true;
+ } else {
+ requireModifyRouting |= true;
}
}
- boolean hasPermissionModifyAudioRouting =
- (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
- android.Manifest.permission.MODIFY_AUDIO_ROUTING));
- if (hasPermissionModifyAudioRouting) {
- return true;
+ if (requireCaptureAudioOrMediaOutputPerm
+ && !callerHasPermission(android.Manifest.permission.CAPTURE_MEDIA_OUTPUT)
+ && !callerHasPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT)) {
+ Log.e(TAG, "Privileged audio capture requires CAPTURE_MEDIA_OUTPUT or "
+ + "CAPTURE_AUDIO_OUTPUT system permission");
+ return false;
}
- return false;
+
+ if (requireValidProjection && !canProjectAudio(projection)) {
+ return false;
+ }
+
+ if (requireModifyRouting
+ && !callerHasPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)) {
+ Log.e(TAG, "Can not capture audio without MODIFY_AUDIO_ROUTING");
+ return false;
+ }
+
+ return true;
}
- private boolean hasPermission(String permission) {
- return PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(permission);
+
+ private boolean callerHasPermission(String permission) {
+ return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED;
}
/** @return true if projection is a valid MediaProjection that can project audio. */
private boolean canProjectAudio(IMediaProjection projection) {
if (projection == null) {
+ Log.e(TAG, "MediaProjection is null");
return false;
}
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 7733d6779e48..8de259516890 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -42,6 +42,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
+import com.android.server.wm.WindowManagerInternal;
import java.util.ArrayList;
import java.util.Collection;
@@ -90,8 +91,10 @@ public class CameraServiceProxy extends SystemService
private ICameraService mCameraServiceRaw;
+ // Map of currently active camera IDs
private final ArrayMap<String, CameraUsageEvent> mActiveCameraUsage = new ArrayMap<>();
private final List<CameraUsageEvent> mCameraUsageHistory = new ArrayList<>();
+
private final MetricsLogger mLogger = new MetricsLogger();
private static final String NFC_NOTIFICATION_PROP = "ro.camera.notify_nfc";
private static final String NFC_SERVICE_BINDER_NAME = "nfc";
@@ -415,6 +418,24 @@ public class CameraServiceProxy extends SystemService
}
break;
case ICameraServiceProxy.CAMERA_STATE_ACTIVE:
+ // Check current active camera IDs to see if this package is already talking to
+ // some camera
+ boolean alreadyActivePackage = false;
+ for (int i = 0; i < mActiveCameraUsage.size(); i++) {
+ if (mActiveCameraUsage.valueAt(i).mClientName.equals(clientName)) {
+ alreadyActivePackage = true;
+ break;
+ }
+ }
+ // If not already active, notify window manager about this new package using a
+ // camera
+ if (!alreadyActivePackage) {
+ WindowManagerInternal wmi =
+ LocalServices.getService(WindowManagerInternal.class);
+ wmi.addNonHighRefreshRatePackage(clientName);
+ }
+
+ // Update activity events
CameraUsageEvent newEvent = new CameraUsageEvent(facing, clientName, apiLevel);
CameraUsageEvent oldEvent = mActiveCameraUsage.put(cameraId, newEvent);
if (oldEvent != null) {
@@ -426,13 +447,31 @@ public class CameraServiceProxy extends SystemService
case ICameraServiceProxy.CAMERA_STATE_IDLE:
case ICameraServiceProxy.CAMERA_STATE_CLOSED:
CameraUsageEvent doneEvent = mActiveCameraUsage.remove(cameraId);
- if (doneEvent != null) {
- doneEvent.markCompleted();
- mCameraUsageHistory.add(doneEvent);
- if (mCameraUsageHistory.size() > MAX_USAGE_HISTORY) {
- dumpUsageEvents();
+ if (doneEvent == null) break;
+
+ doneEvent.markCompleted();
+ mCameraUsageHistory.add(doneEvent);
+ if (mCameraUsageHistory.size() > MAX_USAGE_HISTORY) {
+ dumpUsageEvents();
+ }
+
+ // Check current active camera IDs to see if this package is still talking to
+ // some camera
+ boolean stillActivePackage = false;
+ for (int i = 0; i < mActiveCameraUsage.size(); i++) {
+ if (mActiveCameraUsage.valueAt(i).mClientName.equals(clientName)) {
+ stillActivePackage = true;
+ break;
}
}
+ // If not longer active, notify window manager about this package being done
+ // with camera
+ if (!stillActivePackage) {
+ WindowManagerInternal wmi =
+ LocalServices.getService(WindowManagerInternal.class);
+ wmi.removeNonHighRefreshRatePackage(clientName);
+ }
+
break;
}
boolean isEmpty = mActiveCameraUsage.isEmpty();
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index d28482ef82ab..af25ad56a2a7 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -16,11 +16,14 @@
package com.android.server.clipboard;
+import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
+
+import android.Manifest;
import android.annotation.Nullable;
-import android.app.ActivityManager;
+import android.annotation.UserIdInt;
+import android.app.ActivityManagerInternal;
import android.app.AppGlobals;
import android.app.AppOpsManager;
-import android.app.IActivityManager;
import android.app.IUriGrantsManager;
import android.app.KeyguardManager;
import android.app.UriGrantsManager;
@@ -145,6 +148,11 @@ class HostClipboardMonitor implements Runnable {
/**
* Implementation of the clipboard for copy and paste.
+ * <p>
+ * Caution: exception for clipboard data and isInternalSysWindowAppWithWindowFocus, any of data
+ * is accessed by userId or uid should be in * the try segment between
+ * Binder.clearCallingIdentity and Binder.restoreCallingIdentity.
+ * </p>
*/
public class ClipboardService extends SystemService {
@@ -152,7 +160,7 @@ public class ClipboardService extends SystemService {
private static final boolean IS_EMULATOR =
SystemProperties.getBoolean("ro.kernel.qemu", false);
- private final IActivityManager mAm;
+ private final ActivityManagerInternal mAmInternal;
private final IUriGrantsManager mUgm;
private final UriGrantsManagerInternal mUgmInternal;
private final WindowManagerInternal mWm;
@@ -173,7 +181,7 @@ public class ClipboardService extends SystemService {
public ClipboardService(Context context) {
super(context);
- mAm = ActivityManager.getService();
+ mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
mUgm = UriGrantsManager.getService();
mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
mWm = LocalServices.getService(WindowManagerInternal.class);
@@ -244,6 +252,87 @@ public class ClipboardService extends SystemService {
}
}
+ /**
+ * To check if the application has granted the INTERNAL_SYSTEM_WINDOW permission and window
+ * focus.
+ * <p>
+ * All of applications granted INTERNAL_SYSTEM_WINDOW has the risk to leak clip information to
+ * the other user because INTERNAL_SYSTEM_WINDOW is signature level. i.e. platform key. Because
+ * some of applications have both of INTERNAL_SYSTEM_WINDOW and INTERACT_ACROSS_USERS_FULL at
+ * the same time, that means they show the same window to all of users.
+ * </p><p>
+ * Unfortunately, all of applications with INTERNAL_SYSTEM_WINDOW starts very early and then
+ * the real window show is belong to user 0 rather user X. The result of
+ * WindowManager.isUidFocused checking user X window is false.
+ * </p>
+ * @return true if the app granted INTERNAL_SYSTEM_WINDOW permission.
+ */
+ private boolean isInternalSysWindowAppWithWindowFocus(String callingPackage) {
+ // Shell can access the clipboard for testing purposes.
+ if (mPm.checkPermission(Manifest.permission.INTERNAL_SYSTEM_WINDOW,
+ callingPackage) == PackageManager.PERMISSION_GRANTED) {
+ if (mWm.isUidFocused(Binder.getCallingUid())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * To get the validate current userId.
+ * <p>
+ * The intending userId needs to be validated by ActivityManagerInternal.handleIncomingUser.
+ * To check if the uid of the process have the permission to run as the userId.
+ * e.x. INTERACT_ACROSS_USERS_FULL or INTERACT_ACROSS_USERS permission granted.
+ * </p>
+ * <p>
+ * The application with the granted INTERNAL_SYSTEM_WINDOW permission should run as the output
+ * of ActivityManagerInternal.handleIncomingUser rather the userId of Binder.getCAllingUid().
+ * To use the userId of Binder.getCallingUid() is the root cause that leaks the information
+ * comes from user 0 to user X.
+ * </p>
+ *
+ * @param packageName the package name of the calling side
+ * @param userId the userId passed by the calling side
+ * @return return the intending userId that has been validated by ActivityManagerInternal.
+ */
+ @UserIdInt
+ private int getIntendingUserId(String packageName, @UserIdInt int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final int callingUserId = UserHandle.getUserId(callingUid);
+ if (!UserManager.supportsMultipleUsers() || callingUserId == userId) {
+ return callingUserId;
+ }
+
+ int intendingUserId = callingUserId;
+ intendingUserId = mAmInternal.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, false /* allow all */, ALLOW_FULL_ONLY,
+ "checkClipboardServiceCallingUser", packageName);
+
+ return intendingUserId;
+ }
+
+ /**
+ * To get the current running uid who is intend to run as.
+ * In ording to distinguish the nameing and reducing the confusing names, the client client
+ * side pass userId that is intend to run as,
+ * @return return IntentingUid = validated intenting userId +
+ * UserHandle.getAppId(Binder.getCallingUid())
+ */
+ private int getIntendingUid(String packageName, @UserIdInt int userId) {
+ return UserHandle.getUid(getIntendingUserId(packageName, userId),
+ UserHandle.getAppId(Binder.getCallingUid()));
+ }
+
+ /**
+ * To handle the difference between userId and intendingUserId, uid and intendingUid.
+ *
+ * userId means that comes from the calling side and should be validated by
+ * ActivityManagerInternal.handleIncomingUser.
+ * After validation of ActivityManagerInternal.handleIncomingUser, the userId is called
+ * 'intendingUserId' and the uid is called 'intendingUid'.
+ */
private class ClipboardImpl extends IClipboard.Stub {
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
@@ -260,92 +349,112 @@ public class ClipboardService extends SystemService {
}
@Override
- public void setPrimaryClip(ClipData clip, String callingPackage) {
+ public void setPrimaryClip(ClipData clip, String callingPackage, @UserIdInt int userId) {
synchronized (this) {
if (clip == null || clip.getItemCount() <= 0) {
throw new IllegalArgumentException("No items");
}
- final int callingUid = Binder.getCallingUid();
+ final int intendingUid = getIntendingUid(callingPackage, userId);
+ final int intendingUserId = UserHandle.getUserId(intendingUid);
if (!clipboardAccessAllowed(AppOpsManager.OP_WRITE_CLIPBOARD, callingPackage,
- callingUid)) {
+ intendingUid, intendingUserId)) {
return;
}
- checkDataOwnerLocked(clip, callingUid);
- setPrimaryClipInternal(clip, callingUid);
+ checkDataOwnerLocked(clip, intendingUid);
+ setPrimaryClipInternal(clip, intendingUid);
}
}
@Override
- public void clearPrimaryClip(String callingPackage) {
+ public void clearPrimaryClip(String callingPackage, @UserIdInt int userId) {
synchronized (this) {
- final int callingUid = Binder.getCallingUid();
+ final int intendingUid = getIntendingUid(callingPackage, userId);
+ final int intendingUserId = UserHandle.getUserId(intendingUid);
if (!clipboardAccessAllowed(AppOpsManager.OP_WRITE_CLIPBOARD, callingPackage,
- callingUid)) {
+ intendingUid, intendingUserId)) {
return;
}
- setPrimaryClipInternal(null, callingUid);
+ setPrimaryClipInternal(null, intendingUid);
}
}
@Override
- public ClipData getPrimaryClip(String pkg) {
+ public ClipData getPrimaryClip(String pkg, @UserIdInt int userId) {
synchronized (this) {
+ final int intendingUid = getIntendingUid(pkg, userId);
+ final int intendingUserId = UserHandle.getUserId(intendingUid);
if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, pkg,
- Binder.getCallingUid()) || isDeviceLocked()) {
+ intendingUid, intendingUserId)
+ || isDeviceLocked(intendingUserId)) {
return null;
}
- addActiveOwnerLocked(Binder.getCallingUid(), pkg);
- return getClipboard().primaryClip;
+ addActiveOwnerLocked(intendingUid, pkg);
+ return getClipboard(intendingUserId).primaryClip;
}
}
@Override
- public ClipDescription getPrimaryClipDescription(String callingPackage) {
+ public ClipDescription getPrimaryClipDescription(String callingPackage,
+ @UserIdInt int userId) {
synchronized (this) {
+ final int intendingUid = getIntendingUid(callingPackage, userId);
+ final int intendingUserId = UserHandle.getUserId(intendingUid);
if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage,
- Binder.getCallingUid()) || isDeviceLocked()) {
+ intendingUid, intendingUserId)
+ || isDeviceLocked(intendingUserId)) {
return null;
}
- PerUserClipboard clipboard = getClipboard();
- return clipboard.primaryClip != null ? clipboard.primaryClip.getDescription() : null;
+ PerUserClipboard clipboard = getClipboard(intendingUserId);
+ return clipboard.primaryClip != null
+ ? clipboard.primaryClip.getDescription() : null;
}
}
@Override
- public boolean hasPrimaryClip(String callingPackage) {
+ public boolean hasPrimaryClip(String callingPackage, @UserIdInt int userId) {
synchronized (this) {
+ final int intendingUid = getIntendingUid(callingPackage, userId);
+ final int intendingUserId = UserHandle.getUserId(intendingUid);
if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage,
- Binder.getCallingUid()) || isDeviceLocked()) {
+ intendingUid, intendingUserId)
+ || isDeviceLocked(intendingUserId)) {
return false;
}
- return getClipboard().primaryClip != null;
+ return getClipboard(intendingUserId).primaryClip != null;
}
}
@Override
public void addPrimaryClipChangedListener(IOnPrimaryClipChangedListener listener,
- String callingPackage) {
+ String callingPackage, @UserIdInt int userId) {
synchronized (this) {
- getClipboard().primaryClipListeners.register(listener,
- new ListenerInfo(Binder.getCallingUid(), callingPackage));
+ final int intendingUid = getIntendingUid(callingPackage, userId);
+ final int intendingUserId = UserHandle.getUserId(intendingUid);
+ getClipboard(intendingUserId).primaryClipListeners.register(listener,
+ new ListenerInfo(intendingUid, callingPackage));
}
}
@Override
- public void removePrimaryClipChangedListener(IOnPrimaryClipChangedListener listener) {
+ public void removePrimaryClipChangedListener(IOnPrimaryClipChangedListener listener,
+ String callingPackage, @UserIdInt int userId) {
synchronized (this) {
- getClipboard().primaryClipListeners.unregister(listener);
+ final int intendingUserId = getIntendingUserId(callingPackage, userId);
+ getClipboard(intendingUserId).primaryClipListeners.unregister(listener);
}
}
@Override
- public boolean hasClipboardText(String callingPackage) {
+ public boolean hasClipboardText(String callingPackage, int userId) {
synchronized (this) {
+ final int intendingUid = getIntendingUid(callingPackage, userId);
+ final int intendingUserId = UserHandle.getUserId(intendingUid);
if (!clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, callingPackage,
- Binder.getCallingUid()) || isDeviceLocked()) {
+ intendingUid, intendingUserId)
+ || isDeviceLocked(intendingUserId)) {
return false;
}
- PerUserClipboard clipboard = getClipboard();
+ PerUserClipboard clipboard = getClipboard(intendingUserId);
if (clipboard.primaryClip != null) {
CharSequence text = clipboard.primaryClip.getItemAt(0).getText();
return text != null && text.length() > 0;
@@ -355,11 +464,7 @@ public class ClipboardService extends SystemService {
}
};
- private PerUserClipboard getClipboard() {
- return getClipboard(UserHandle.getCallingUserId());
- }
-
- private PerUserClipboard getClipboard(int userId) {
+ private PerUserClipboard getClipboard(@UserIdInt int userId) {
synchronized (mClipboards) {
PerUserClipboard puc = mClipboards.get(userId);
if (puc == null) {
@@ -370,7 +475,7 @@ public class ClipboardService extends SystemService {
}
}
- List<UserInfo> getRelatedProfiles(int userId) {
+ List<UserInfo> getRelatedProfiles(@UserIdInt int userId) {
final List<UserInfo> related;
final long origId = Binder.clearCallingIdentity();
try {
@@ -397,7 +502,7 @@ public class ClipboardService extends SystemService {
}
}
- void setPrimaryClipInternal(@Nullable ClipData clip, int callingUid) {
+ void setPrimaryClipInternal(@Nullable ClipData clip, int uid) {
// Push clipboard to host, if any
if (mHostClipboardMonitor != null) {
if (clip == null) {
@@ -412,8 +517,8 @@ public class ClipboardService extends SystemService {
}
// Update this user
- final int userId = UserHandle.getUserId(callingUid);
- setPrimaryClipInternal(getClipboard(userId), clip, callingUid);
+ final int userId = UserHandle.getUserId(uid);
+ setPrimaryClipInternal(getClipboard(userId), clip, uid);
// Update related users
List<UserInfo> related = getRelatedProfiles(userId);
@@ -426,11 +531,15 @@ public class ClipboardService extends SystemService {
// primary clip in related users to prevent pasting stale content.
if (!canCopy) {
clip = null;
+ } else if (clip == null) {
+ // do nothing for canCopy == true and clip == null case
+ // To prevent from NPE happen in 'new ClipData(clip)' when run
+ // android.content.cts.ClipboardManagerTest#testClearPrimaryClip
} else {
// We want to fix the uris of the related user's clip without changing the
// uris of the current user's clip.
// So, copy the ClipData, and then copy all the items, so that nothing
- // is shared in memmory.
+ // is shared in memory.
clip = new ClipData(clip);
for (int i = clip.getItemCount() - 1; i >= 0; i--) {
clip.setItemAt(i, new ClipData.Item(clip.getItemAt(i)));
@@ -443,7 +552,7 @@ public class ClipboardService extends SystemService {
final boolean canCopyIntoProfile = !hasRestriction(
UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE, id);
if (canCopyIntoProfile) {
- setPrimaryClipInternal(getClipboard(id), clip, callingUid);
+ setPrimaryClipInternal(getClipboard(id), clip, uid);
}
}
}
@@ -452,7 +561,7 @@ public class ClipboardService extends SystemService {
}
void setPrimaryClipInternal(PerUserClipboard clipboard, @Nullable ClipData clip,
- int callingUid) {
+ int uid) {
revokeUris(clipboard);
clipboard.activePermissionOwners.clear();
if (clip == null && clipboard.primaryClip == null) {
@@ -460,7 +569,7 @@ public class ClipboardService extends SystemService {
}
clipboard.primaryClip = clip;
if (clip != null) {
- clipboard.primaryClipUid = callingUid;
+ clipboard.primaryClipUid = uid;
} else {
clipboard.primaryClipUid = android.os.Process.NOBODY_UID;
}
@@ -479,7 +588,7 @@ public class ClipboardService extends SystemService {
clipboard.primaryClipListeners.getBroadcastCookie(i);
if (clipboardAccessAllowed(AppOpsManager.OP_READ_CLIPBOARD, li.mPackageName,
- li.mUid)) {
+ li.mUid, UserHandle.getUserId(li.mUid))) {
clipboard.primaryClipListeners.getBroadcastItem(i)
.dispatchPrimaryClipChanged();
}
@@ -494,13 +603,12 @@ public class ClipboardService extends SystemService {
}
}
- private boolean isDeviceLocked() {
- int callingUserId = UserHandle.getCallingUserId();
+ private boolean isDeviceLocked(@UserIdInt int userId) {
final long token = Binder.clearCallingIdentity();
try {
final KeyguardManager keyguardManager = getContext().getSystemService(
KeyguardManager.class);
- return keyguardManager != null && keyguardManager.isDeviceLocked(callingUserId);
+ return keyguardManager != null && keyguardManager.isDeviceLocked(userId);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -585,7 +693,7 @@ public class ClipboardService extends SystemService {
} finally {
Binder.restoreCallingIdentity(oldIdentity);
}
- PerUserClipboard clipboard = getClipboard();
+ PerUserClipboard clipboard = getClipboard(UserHandle.getUserId(uid));
if (clipboard.primaryClip != null && !clipboard.activePermissionOwners.contains(pkg)) {
final int N = clipboard.primaryClip.getItemCount();
for (int i=0; i<N; i++) {
@@ -630,9 +738,10 @@ public class ClipboardService extends SystemService {
}
}
- private boolean clipboardAccessAllowed(int op, String callingPackage, int callingUid) {
+ private boolean clipboardAccessAllowed(int op, String callingPackage, int uid,
+ @UserIdInt int userId) {
// Check the AppOp.
- if (mAppOps.noteOp(op, callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
+ if (mAppOps.noteOp(op, uid, callingPackage) != AppOpsManager.MODE_ALLOWED) {
return false;
}
// Shell can access the clipboard for testing purposes.
@@ -641,7 +750,6 @@ 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, userId);
if (!TextUtils.isEmpty(defaultIme)) {
@@ -654,16 +762,31 @@ public class ClipboardService extends SystemService {
switch (op) {
case AppOpsManager.OP_READ_CLIPBOARD:
// Clipboard can only be read by applications with focus..
- boolean allowed = mWm.isUidFocused(callingUid);
+ // or the application have the INTERNAL_SYSTEM_WINDOW and INTERACT_ACROSS_USERS_FULL
+ // at the same time. e.x. SystemUI. It needs to check the window focus of
+ // Binder.getCallingUid(). Without checking, the user X can't copy any thing from
+ // INTERNAL_SYSTEM_WINDOW to the other applications.
+ boolean allowed = mWm.isUidFocused(uid)
+ || isInternalSysWindowAppWithWindowFocus(callingPackage);
if (!allowed && mContentCaptureInternal != null) {
// ...or the Content Capture Service
- allowed = mContentCaptureInternal.isContentCaptureServiceForUser(callingUid,
- userId);
+ // The uid parameter of mContentCaptureInternal.isContentCaptureServiceForUser
+ // is used to check if the uid has the permission BIND_CONTENT_CAPTURE_SERVICE.
+ // if the application has the permission, let it to access user's clipboard.
+ // To passed synthesized uid user#10_app#systemui may not tell the real uid.
+ // userId must pass intending userId. i.e. user#10.
+ allowed = mContentCaptureInternal.isContentCaptureServiceForUser(
+ Binder.getCallingUid(), userId);
}
if (!allowed && mAutofillInternal != null) {
// ...or the Augmented Autofill Service
- allowed = mAutofillInternal.isAugmentedAutofillServiceForUser(callingUid,
- userId);
+ // The uid parameter of mAutofillInternal.isAugmentedAutofillServiceForUser
+ // is used to check if the uid has the permission BIND_AUTOFILL_SERVICE.
+ // if the application has the permission, let it to access user's clipboard.
+ // To passed synthesized uid user#10_app#systemui may not tell the real uid.
+ // userId must pass intending userId. i.e. user#10.
+ allowed = mAutofillInternal.isAugmentedAutofillServiceForUser(
+ Binder.getCallingUid(), userId);
}
if (!allowed) {
Slog.e(TAG, "Denying clipboard access to " + callingPackage
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index d8b7c2eb5d4c..fa8c48bdc7f7 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1170,7 +1170,7 @@ public class SyncManager {
}
private void removeSyncsForAuthority(EndPoint info, String why) {
- mLogger.log("removeSyncsForAuthority: ", info);
+ mLogger.log("removeSyncsForAuthority: ", info, why);
verifyJobScheduler();
List<SyncOperation> ops = getAllPendingSyncs();
for (SyncOperation op: ops) {
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index c7a3f4b173c3..e09c661c627b 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -1027,7 +1027,7 @@ public class SyncStorageEngine {
* Called when the set of account has changed, given the new array of
* active accounts.
*/
- public void removeStaleAccounts(@Nullable Account[] accounts, int userId) {
+ public void removeStaleAccounts(@Nullable Account[] currentAccounts, int userId) {
synchronized (mAuthorities) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Slog.v(TAG, "Updating for new accounts...");
@@ -1036,9 +1036,11 @@ public class SyncStorageEngine {
Iterator<AccountInfo> accIt = mAccounts.values().iterator();
while (accIt.hasNext()) {
AccountInfo acc = accIt.next();
- if ((accounts == null) || (
- (acc.accountAndUser.userId == userId)
- && !ArrayUtils.contains(accounts, acc.accountAndUser.account))) {
+ if (acc.accountAndUser.userId != userId) {
+ continue; // Irrelevant user.
+ }
+ if ((currentAccounts == null)
+ || !ArrayUtils.contains(currentAccounts, acc.accountAndUser.account)) {
// This account no longer exists...
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Slog.v(TAG, "Account removed: " + acc.accountAndUser);
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 6d0137551729..99341d1c96ae 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -254,6 +254,9 @@ public final class DisplayManagerService extends SystemService {
// device).
private Point mStableDisplaySize = new Point();
+ // Whether the system has finished booting or not.
+ private boolean mSystemReady;
+
// The top inset of the default display.
// This gets persisted so that the boot animation knows how to transition from the display's
// full size to the size configured by the user. Right now we only persist and animate the top
@@ -330,6 +333,8 @@ public final class DisplayManagerService extends SystemService {
mCurrentUserId = UserHandle.USER_SYSTEM;
ColorSpace[] colorSpaces = SurfaceControl.getCompositionColorSpaces();
mWideColorSpace = colorSpaces[1];
+
+ mSystemReady = false;
}
public void setupSchedulerPolicies() {
@@ -418,6 +423,10 @@ public final class DisplayManagerService extends SystemService {
synchronized (mSyncRoot) {
mSafeMode = safeMode;
mOnlyCore = onlyCore;
+ mSystemReady = true;
+ // Just in case the top inset changed before the system was ready. At this point, any
+ // relevant configuration should be in place.
+ recordTopInsetLocked(mLogicalDisplays.get(Display.DEFAULT_DISPLAY));
}
mDisplayModeDirector.setListener(new AllowedDisplayModeObserver());
@@ -1057,7 +1066,10 @@ public final class DisplayManagerService extends SystemService {
}
private void recordTopInsetLocked(@Nullable LogicalDisplay d) {
- if (d == null) {
+ // We must only persist the inset after boot has completed, otherwise we will end up
+ // overwriting the persisted value before the masking flag has been loaded from the
+ // resource overlay.
+ if (!mSystemReady || d == null) {
return;
}
int topInset = d.getInsets().top;
diff --git a/services/core/java/com/android/server/location/GnssConfiguration.java b/services/core/java/com/android/server/location/GnssConfiguration.java
index aa51aec216eb..86a84e312899 100644
--- a/services/core/java/com/android/server/location/GnssConfiguration.java
+++ b/services/core/java/com/android/server/location/GnssConfiguration.java
@@ -70,7 +70,6 @@ class GnssConfiguration {
private static final String CONFIG_GPS_LOCK = "GPS_LOCK";
private static final String CONFIG_ES_EXTENSION_SEC = "ES_EXTENSION_SEC";
public static final String CONFIG_NFW_PROXY_APPS = "NFW_PROXY_APPS";
- public static final String CONFIG_ES_NOTIFY_INT = "ES_NOTIFY_INT";
// Limit on NI emergency mode time extension after emergency sessions ends
private static final int MAX_EMERGENCY_MODE_EXTENSION_SECONDS = 300; // 5 minute maximum
@@ -200,14 +199,6 @@ class GnssConfiguration {
}
/**
- * Returns the value of config parameter ES_NOTIFY_INT or {@code defaulEsNotify} if no
- * value is provided or if there is an error parsing the configured value.
- */
- int getEsNotify(int defaulEsNotify) {
- return getIntConfig(CONFIG_ES_NOTIFY_INT, defaulEsNotify);
- }
-
- /**
* Updates the GNSS HAL satellite blacklist.
*/
void setSatelliteBlacklist(int[] constellations, int[] svids) {
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index b2315c7b7314..f28bce5d5e7b 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -966,8 +966,9 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
}
private void updateEnabled() {
- // Generally follow location setting
- boolean enabled = mContext.getSystemService(LocationManager.class).isLocationEnabled();
+ // Generally follow location setting for current user
+ boolean enabled = mContext.getSystemService(LocationManager.class)
+ .isLocationEnabledForUser(UserHandle.CURRENT);
// ... but disable if PowerManager overrides
enabled &= !mDisableGpsForPowerManager;
diff --git a/services/core/java/com/android/server/location/GnssVisibilityControl.java b/services/core/java/com/android/server/location/GnssVisibilityControl.java
index c49d9000c1dd..8d4ad7f30821 100644
--- a/services/core/java/com/android/server/location/GnssVisibilityControl.java
+++ b/services/core/java/com/android/server/location/GnssVisibilityControl.java
@@ -16,14 +16,19 @@
package com.android.server.location;
+import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.AppOpsManager;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.location.LocationManager;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
@@ -35,6 +40,7 @@ import android.util.StatsLog;
import com.android.internal.R;
import com.android.internal.location.GpsNetInitiatedHandler;
+import com.android.internal.notification.SystemNotificationChannels;
import java.util.Arrays;
import java.util.List;
@@ -58,10 +64,8 @@ class GnssVisibilityControl {
// Max wait time for synchronous method onGpsEnabledChanged() to run.
private static final long ON_GPS_ENABLED_CHANGED_TIMEOUT_MILLIS = 3 * 1000;
- // Valid values for config parameter es_notify_int for posting notification in the status
- // bar for non-framework location requests in user-initiated emergency use cases.
- private static final int ES_NOTIFY_NONE = 0;
- private static final int ES_NOTIFY_ALL = 1;
+ // How long to display location icon for each non-framework non-emergency location request.
+ private static final long LOCATION_ICON_DISPLAY_DURATION_MILLIS = 5 * 1000;
// Wakelocks
private static final String WAKELOCK_KEY = TAG;
@@ -74,14 +78,23 @@ class GnssVisibilityControl {
private final Handler mHandler;
private final Context mContext;
private final GpsNetInitiatedHandler mNiHandler;
+ private final Notification mEmergencyLocationUserNotification;
private boolean mIsGpsEnabled;
- private boolean mEsNotify;
+
+ private static final class ProxyAppState {
+ private boolean mHasLocationPermission;
+ private boolean mIsLocationIconOn;
+
+ private ProxyAppState(boolean hasLocationPermission) {
+ mHasLocationPermission = hasLocationPermission;
+ }
+ }
// Number of non-framework location access proxy apps is expected to be small (< 5).
- private static final int ARRAY_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS = 7;
- private ArrayMap<String, Boolean> mProxyAppToLocationPermissions = new ArrayMap<>(
- ARRAY_MAP_INITIAL_CAPACITY_PROXY_APP_TO_LOCATION_PERMISSIONS);
+ private static final int ARRAY_MAP_INITIAL_CAPACITY_PROXY_APPS_STATE = 5;
+ private ArrayMap<String, ProxyAppState> mProxyAppsState = new ArrayMap<>(
+ ARRAY_MAP_INITIAL_CAPACITY_PROXY_APPS_STATE);
private PackageManager.OnPermissionsChangedListener mOnPermissionsChangedListener =
uid -> runOnHandler(() -> handlePermissionsChanged(uid));
@@ -94,6 +107,7 @@ class GnssVisibilityControl {
mNiHandler = niHandler;
mAppOps = mContext.getSystemService(AppOpsManager.class);
mPackageManager = mContext.getPackageManager();
+ mEmergencyLocationUserNotification = createEmergencyLocationUserNotification(mContext);
// Complete initialization as the first event to run in mHandler thread. After that,
// all object state read/update events run in the mHandler thread.
@@ -135,22 +149,7 @@ class GnssVisibilityControl {
void onConfigurationUpdated(GnssConfiguration configuration) {
// The configuration object must be accessed only in the caller thread and not in mHandler.
List<String> nfwLocationAccessProxyApps = configuration.getProxyApps();
- int esNotify = configuration.getEsNotify(ES_NOTIFY_NONE);
- runOnHandler(() -> {
- setEsNotify(esNotify);
- handleUpdateProxyApps(nfwLocationAccessProxyApps);
- });
- }
-
- private void setEsNotify(int esNotify) {
- if (esNotify != ES_NOTIFY_NONE && esNotify != ES_NOTIFY_ALL) {
- Log.e(TAG, "Config parameter " + GnssConfiguration.CONFIG_ES_NOTIFY_INT
- + " is set to invalid value: " + esNotify
- + ". Using default value: " + ES_NOTIFY_NONE);
- esNotify = ES_NOTIFY_NONE;
- }
-
- mEsNotify = (esNotify == ES_NOTIFY_ALL);
+ runOnHandler(() -> handleUpdateProxyApps(nfwLocationAccessProxyApps));
}
private void handleInitialize() {
@@ -188,18 +187,18 @@ class GnssVisibilityControl {
}
private void handleProxyAppPackageUpdate(String pkgName, String action) {
- final Boolean locationPermission = mProxyAppToLocationPermissions.get(pkgName);
- if (locationPermission == null) {
+ final ProxyAppState proxyAppState = mProxyAppsState.get(pkgName);
+ if (proxyAppState == null) {
return; // ignore, pkgName is not one of the proxy apps in our list.
}
if (DEBUG) Log.d(TAG, "Proxy app " + pkgName + " package changed: " + action);
final boolean updatedLocationPermission = shouldEnableLocationPermissionInGnssHal(pkgName);
- if (locationPermission != updatedLocationPermission) {
+ if (proxyAppState.mHasLocationPermission != updatedLocationPermission) {
// Permission changed. So, update the GNSS HAL with the updated list.
Log.i(TAG, "Proxy app " + pkgName + " location permission changed."
+ " IsLocationPermissionEnabled: " + updatedLocationPermission);
- mProxyAppToLocationPermissions.put(pkgName, updatedLocationPermission);
+ proxyAppState.mHasLocationPermission = updatedLocationPermission;
updateNfwLocationAccessProxyAppsInGnssHal();
}
}
@@ -211,35 +210,53 @@ class GnssVisibilityControl {
if (nfwLocationAccessProxyApps.isEmpty()) {
// Stop listening for app permission changes. Clear the app list in GNSS HAL.
- if (!mProxyAppToLocationPermissions.isEmpty()) {
+ if (!mProxyAppsState.isEmpty()) {
mPackageManager.removeOnPermissionsChangeListener(mOnPermissionsChangedListener);
- mProxyAppToLocationPermissions.clear();
+ resetProxyAppsState();
updateNfwLocationAccessProxyAppsInGnssHal();
}
return;
}
- if (mProxyAppToLocationPermissions.isEmpty()) {
+ if (mProxyAppsState.isEmpty()) {
mPackageManager.addOnPermissionsChangeListener(mOnPermissionsChangedListener);
} else {
- mProxyAppToLocationPermissions.clear();
+ resetProxyAppsState();
}
for (String proxyAppPkgName : nfwLocationAccessProxyApps) {
- mProxyAppToLocationPermissions.put(proxyAppPkgName,
- shouldEnableLocationPermissionInGnssHal(proxyAppPkgName));
+ ProxyAppState proxyAppState = new ProxyAppState(shouldEnableLocationPermissionInGnssHal(
+ proxyAppPkgName));
+ mProxyAppsState.put(proxyAppPkgName, proxyAppState);
}
updateNfwLocationAccessProxyAppsInGnssHal();
}
+ private void resetProxyAppsState() {
+ // Clear location icons displayed.
+ for (Map.Entry<String, ProxyAppState> entry : mProxyAppsState.entrySet()) {
+ ProxyAppState proxyAppState = entry.getValue();
+ if (!proxyAppState.mIsLocationIconOn) {
+ continue;
+ }
+
+ mHandler.removeCallbacksAndMessages(proxyAppState);
+ final ApplicationInfo proxyAppInfo = getProxyAppInfo(entry.getKey());
+ if (proxyAppInfo != null) {
+ clearLocationIcon(proxyAppState, proxyAppInfo.uid, entry.getKey());
+ }
+ }
+ mProxyAppsState.clear();
+ }
+
private boolean isProxyAppListUpdated(List<String> nfwLocationAccessProxyApps) {
- if (nfwLocationAccessProxyApps.size() != mProxyAppToLocationPermissions.size()) {
+ if (nfwLocationAccessProxyApps.size() != mProxyAppsState.size()) {
return true;
}
for (String nfwLocationAccessProxyApp : nfwLocationAccessProxyApps) {
- if (!mProxyAppToLocationPermissions.containsKey(nfwLocationAccessProxyApp)) {
+ if (!mProxyAppsState.containsKey(nfwLocationAccessProxyApp)) {
return true;
}
}
@@ -278,9 +295,6 @@ class GnssVisibilityControl {
private static final byte NFW_RESPONSE_TYPE_ACCEPTED_NO_LOCATION_PROVIDED = 1;
private static final byte NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED = 2;
- // This must match with NfwProtocolStack enum in IGnssVisibilityControlCallback.hal.
- private static final byte NFW_PROTOCOL_STACK_SUPL = 1;
-
private final String mProxyAppPackageName;
private final byte mProtocolStack;
private final String mOtherProtocolStackName;
@@ -341,18 +355,14 @@ class GnssVisibilityControl {
private boolean isEmergencyRequestNotification() {
return mInEmergencyMode && !isRequestAttributedToProxyApp();
}
-
- private boolean isRequestTypeSupl() {
- return mProtocolStack == NFW_PROTOCOL_STACK_SUPL;
- }
}
private void handlePermissionsChanged(int uid) {
- if (mProxyAppToLocationPermissions.isEmpty()) {
+ if (mProxyAppsState.isEmpty()) {
return;
}
- for (Map.Entry<String, Boolean> entry : mProxyAppToLocationPermissions.entrySet()) {
+ for (Map.Entry<String, ProxyAppState> entry : mProxyAppsState.entrySet()) {
final String proxyAppPkgName = entry.getKey();
final ApplicationInfo proxyAppInfo = getProxyAppInfo(proxyAppPkgName);
if (proxyAppInfo == null || proxyAppInfo.uid != uid) {
@@ -361,10 +371,11 @@ class GnssVisibilityControl {
final boolean isLocationPermissionEnabled = shouldEnableLocationPermissionInGnssHal(
proxyAppPkgName);
- if (isLocationPermissionEnabled != entry.getValue()) {
+ ProxyAppState proxyAppState = entry.getValue();
+ if (isLocationPermissionEnabled != proxyAppState.mHasLocationPermission) {
Log.i(TAG, "Proxy app " + proxyAppPkgName + " location permission changed."
+ " IsLocationPermissionEnabled: " + isLocationPermissionEnabled);
- entry.setValue(isLocationPermissionEnabled);
+ proxyAppState.mHasLocationPermission = isLocationPermissionEnabled;
updateNfwLocationAccessProxyAppsInGnssHal();
}
return;
@@ -416,8 +427,8 @@ class GnssVisibilityControl {
private String[] getLocationPermissionEnabledProxyApps() {
// Get a count of proxy apps with location permission enabled for array creation size.
int countLocationPermissionEnabledProxyApps = 0;
- for (Boolean hasLocationPermissionEnabled : mProxyAppToLocationPermissions.values()) {
- if (hasLocationPermissionEnabled) {
+ for (ProxyAppState proxyAppState : mProxyAppsState.values()) {
+ if (proxyAppState.mHasLocationPermission) {
++countLocationPermissionEnabledProxyApps;
}
}
@@ -425,10 +436,9 @@ class GnssVisibilityControl {
int i = 0;
String[] locationPermissionEnabledProxyApps =
new String[countLocationPermissionEnabledProxyApps];
- for (Map.Entry<String, Boolean> entry : mProxyAppToLocationPermissions.entrySet()) {
+ for (Map.Entry<String, ProxyAppState> entry : mProxyAppsState.entrySet()) {
final String proxyApp = entry.getKey();
- final boolean hasLocationPermissionEnabled = entry.getValue();
- if (hasLocationPermissionEnabled) {
+ if (entry.getValue().mHasLocationPermission) {
locationPermissionEnabledProxyApps[i++] = proxyApp;
}
}
@@ -444,12 +454,11 @@ class GnssVisibilityControl {
}
final String proxyAppPkgName = nfwNotification.mProxyAppPackageName;
- final Boolean isLocationPermissionEnabled = mProxyAppToLocationPermissions.get(
- proxyAppPkgName);
+ final ProxyAppState proxyAppState = mProxyAppsState.get(proxyAppPkgName);
final boolean isLocationRequestAccepted = nfwNotification.isRequestAccepted();
final boolean isPermissionMismatched =
- (isLocationPermissionEnabled == null) ? isLocationRequestAccepted
- : (isLocationPermissionEnabled != isLocationRequestAccepted);
+ (proxyAppState == null) ? isLocationRequestAccepted
+ : (proxyAppState.mHasLocationPermission != isLocationRequestAccepted);
logEvent(nfwNotification, isPermissionMismatched);
if (!nfwNotification.isRequestAttributedToProxyApp()) {
@@ -464,7 +473,7 @@ class GnssVisibilityControl {
if (DEBUG) {
Log.d(TAG, "Non-framework location request rejected. ProxyAppPackageName field"
+ " is not set in the notification: " + nfwNotification + ". Number of"
- + " configured proxy apps: " + mProxyAppToLocationPermissions.size());
+ + " configured proxy apps: " + mProxyAppsState.size());
}
return;
}
@@ -474,7 +483,7 @@ class GnssVisibilityControl {
return;
}
- if (isLocationPermissionEnabled == null) {
+ if (proxyAppState == null) {
Log.w(TAG, "Could not find proxy app " + proxyAppPkgName + " in the value specified for"
+ " config parameter: " + GnssConfiguration.CONFIG_NFW_PROXY_APPS
+ ". AppOps service not notified for notification: " + nfwNotification);
@@ -489,18 +498,99 @@ class GnssVisibilityControl {
return;
}
- mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, proxyAppInfo.uid, proxyAppPkgName);
+ if (nfwNotification.isLocationProvided()) {
+ showLocationIcon(proxyAppState, nfwNotification, proxyAppInfo.uid, proxyAppPkgName);
+ mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, proxyAppInfo.uid,
+ proxyAppPkgName);
+ }
// Log proxy app permission mismatch between framework and GNSS HAL.
if (isPermissionMismatched) {
Log.w(TAG, "Permission mismatch. Framework proxy app " + proxyAppPkgName
- + " location permission is set to " + isLocationPermissionEnabled
+ + " location permission is set to " + proxyAppState.mHasLocationPermission
+ " but GNSS non-framework location access response type is "
+ nfwNotification.getResponseTypeAsString() + " for notification: "
+ nfwNotification);
}
}
+ private void showLocationIcon(ProxyAppState proxyAppState, NfwNotification nfwNotification,
+ int uid, String proxyAppPkgName) {
+ // If we receive a new NfwNotification before the location icon is turned off for the
+ // previous notification, update the timer to extend the location icon display duration.
+ final boolean isLocationIconOn = proxyAppState.mIsLocationIconOn;
+ if (!isLocationIconOn) {
+ if (!updateLocationIcon(/* displayLocationIcon = */ true, uid, proxyAppPkgName)) {
+ Log.w(TAG, "Failed to show Location icon for notification: " + nfwNotification);
+ return;
+ }
+ proxyAppState.mIsLocationIconOn = true;
+ } else {
+ // Extend timer by canceling the current one and starting a new one.
+ mHandler.removeCallbacksAndMessages(proxyAppState);
+ }
+
+ // Start timer to turn off location icon. proxyAppState is used as a token to cancel timer.
+ if (DEBUG) {
+ Log.d(TAG, "Location icon on. " + (isLocationIconOn ? "Extending" : "Setting")
+ + " icon display timer. Uid: " + uid + ", proxyAppPkgName: " + proxyAppPkgName);
+ }
+ if (!mHandler.postDelayed(() -> handleLocationIconTimeout(proxyAppPkgName),
+ /* token = */ proxyAppState, LOCATION_ICON_DISPLAY_DURATION_MILLIS)) {
+ clearLocationIcon(proxyAppState, uid, proxyAppPkgName);
+ Log.w(TAG, "Failed to show location icon for the full duration for notification: "
+ + nfwNotification);
+ }
+ }
+
+ private void handleLocationIconTimeout(String proxyAppPkgName) {
+ // Get uid again instead of using the one provided in startOp() call as the app could have
+ // been uninstalled and reinstalled during the timeout duration (unlikely in real world).
+ final ApplicationInfo proxyAppInfo = getProxyAppInfo(proxyAppPkgName);
+ if (proxyAppInfo != null) {
+ clearLocationIcon(mProxyAppsState.get(proxyAppPkgName), proxyAppInfo.uid,
+ proxyAppPkgName);
+ }
+ }
+
+ private void clearLocationIcon(@Nullable ProxyAppState proxyAppState, int uid,
+ String proxyAppPkgName) {
+ updateLocationIcon(/* displayLocationIcon = */ false, uid, proxyAppPkgName);
+ if (proxyAppState != null) proxyAppState.mIsLocationIconOn = false;
+ if (DEBUG) {
+ Log.d(TAG, "Location icon off. Uid: " + uid + ", proxyAppPkgName: " + proxyAppPkgName);
+ }
+ }
+
+ private boolean updateLocationIcon(boolean displayLocationIcon, int uid,
+ String proxyAppPkgName) {
+ if (displayLocationIcon) {
+ // Need two calls to startOp() here with different op code so that the proxy app shows
+ // up in the recent location requests page and also the location icon gets displayed.
+ if (mAppOps.startOpNoThrow(AppOpsManager.OP_MONITOR_LOCATION, uid,
+ proxyAppPkgName) != AppOpsManager.MODE_ALLOWED) {
+ return false;
+ }
+ if (mAppOps.startOpNoThrow(AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, uid,
+ proxyAppPkgName) != AppOpsManager.MODE_ALLOWED) {
+ mAppOps.finishOp(AppOpsManager.OP_MONITOR_LOCATION, uid, proxyAppPkgName);
+ return false;
+ }
+ } else {
+ mAppOps.finishOp(AppOpsManager.OP_MONITOR_LOCATION, uid, proxyAppPkgName);
+ mAppOps.finishOp(AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, uid, proxyAppPkgName);
+ }
+ sendHighPowerMonitoringBroadcast();
+ return true;
+ }
+
+ private void sendHighPowerMonitoringBroadcast() {
+ // Send an intent to notify that a high power request has been added/removed so that
+ // the SystemUi checks the state of AppOps and updates the location icon accordingly.
+ Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
+
private void handleEmergencyNfwNotification(NfwNotification nfwNotification) {
boolean isPermissionMismatched = false;
if (!nfwNotification.isRequestAccepted()) {
@@ -517,27 +607,44 @@ class GnssVisibilityControl {
logEvent(nfwNotification, isPermissionMismatched);
- if (mEsNotify && nfwNotification.isLocationProvided()) {
- // Emulate deprecated IGnssNi.hal user notification of emergency NI requests.
- GpsNetInitiatedHandler.GpsNiNotification notification =
- new GpsNetInitiatedHandler.GpsNiNotification();
- notification.notificationId = 0;
- notification.niType = nfwNotification.isRequestTypeSupl()
- ? GpsNetInitiatedHandler.GPS_NI_TYPE_EMERGENCY_SUPL
- : GpsNetInitiatedHandler.GPS_NI_TYPE_UMTS_CTRL_PLANE;
- notification.needNotify = true;
- notification.needVerify = false;
- notification.privacyOverride = false;
- notification.timeout = 0;
- notification.defaultResponse = GpsNetInitiatedHandler.GPS_NI_RESPONSE_NORESP;
- notification.requestorId = nfwNotification.mRequestorId;
- notification.requestorIdEncoding = GpsNetInitiatedHandler.GPS_ENC_NONE;
- notification.text = mContext.getString(R.string.global_action_emergency);
- notification.textEncoding = GpsNetInitiatedHandler.GPS_ENC_NONE;
- mNiHandler.setNiNotification(notification);
+ if (nfwNotification.isLocationProvided()) {
+ postEmergencyLocationUserNotification(nfwNotification);
}
}
+ private void postEmergencyLocationUserNotification(NfwNotification nfwNotification) {
+ // Emulate deprecated IGnssNi.hal user notification of emergency NI requests.
+ NotificationManager notificationManager = (NotificationManager) mContext
+ .getSystemService(Context.NOTIFICATION_SERVICE);
+ if (notificationManager == null) {
+ Log.w(TAG, "Could not notify user of emergency location request. Notification: "
+ + nfwNotification);
+ return;
+ }
+
+ notificationManager.notifyAsUser(/* tag= */ null, /* notificationId= */ 0,
+ mEmergencyLocationUserNotification, UserHandle.ALL);
+ }
+
+ private static Notification createEmergencyLocationUserNotification(Context context) {
+ String firstLineText = context.getString(R.string.gpsNotifTitle);
+ String secondLineText = context.getString(R.string.global_action_emergency);
+ String accessibilityServicesText = firstLineText + " (" + secondLineText + ")";
+ return new Notification.Builder(context, SystemNotificationChannels.NETWORK_ALERTS)
+ .setSmallIcon(com.android.internal.R.drawable.stat_sys_gps_on)
+ .setWhen(0)
+ .setOngoing(true)
+ .setAutoCancel(true)
+ .setColor(context.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setDefaults(0)
+ .setTicker(accessibilityServicesText)
+ .setContentTitle(firstLineText)
+ .setContentText(secondLineText)
+ .setContentIntent(PendingIntent.getBroadcast(context, 0, new Intent(), 0))
+ .build();
+ }
+
private void logEvent(NfwNotification notification, boolean isPermissionMismatched) {
StatsLog.write(StatsLog.GNSS_NFW_NOTIFICATION_REPORTED,
notification.mProxyAppPackageName,
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index b246eb6d38bd..017c1b3f11f5 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -27,7 +27,6 @@ import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTE
import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY;
import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY;
-import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
import static com.android.internal.widget.LockPatternUtils.USER_FRP;
import static com.android.internal.widget.LockPatternUtils.frpCredentialEnabled;
@@ -560,10 +559,11 @@ public class LockSettingsService extends ILockSettings.Stub {
public void onCleanupUser(int userId) {
hideEncryptionNotification(new UserHandle(userId));
- // User is stopped with its CE key evicted. Require strong auth next time to be able to
- // unlock the user's storage. Use STRONG_AUTH_REQUIRED_AFTER_BOOT since stopping and
- // restarting a user later is equivalent to rebooting the device.
- requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_BOOT, userId);
+ // User is stopped with its CE key evicted. Restore strong auth requirement to the default
+ // flags after boot since stopping and restarting a user later is equivalent to rebooting
+ // the device.
+ int strongAuthRequired = LockPatternUtils.StrongAuthTracker.getDefaultFlags(mContext);
+ requireStrongAuth(strongAuthRequired, userId);
}
public void onStartUser(final int userId) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 13b4ab927c59..8c58247cc601 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -46,6 +46,7 @@ import static android.content.Context.BIND_ADJUST_BELOW_PERCEPTIBLE;
import static android.content.Context.BIND_ALLOW_WHITELIST_MANAGEMENT;
import static android.content.Context.BIND_AUTO_CREATE;
import static android.content.Context.BIND_FOREGROUND_SERVICE;
+import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
import static android.content.pm.PackageManager.FEATURE_TELEVISION;
import static android.content.pm.PackageManager.MATCH_ALL;
@@ -82,6 +83,9 @@ import static android.service.notification.NotificationListenerService.REASON_UN
import static android.service.notification.NotificationListenerService.REASON_USER_STOPPED;
import static android.service.notification.NotificationListenerService.TRIM_FULL;
import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
+import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING;
+import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE;
+import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__DOCUMENT_LAUNCH_NOT_ALWAYS;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER;
@@ -131,6 +135,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
@@ -197,6 +202,7 @@ import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.StatsLog;
import android.util.Xml;
import android.util.proto.ProtoOutputStream;
import android.view.accessibility.AccessibilityEvent;
@@ -310,7 +316,6 @@ public class NotificationManagerService extends SystemService {
static final boolean ENABLE_BLOCKED_TOASTS = true;
static final String[] DEFAULT_ALLOWED_ADJUSTMENTS = new String[] {
- Adjustment.KEY_IMPORTANCE,
Adjustment.KEY_CONTEXTUAL_ACTIONS,
Adjustment.KEY_TEXT_REPLIES};
@@ -4822,10 +4827,14 @@ public class NotificationManagerService extends SystemService {
private boolean isNotificationAppropriateToBubble(NotificationRecord r, String pkg, int userId,
NotificationRecord oldRecord) {
Notification notification = r.getNotification();
+ Notification.BubbleMetadata metadata = notification.getBubbleMetadata();
+ boolean intentCanBubble = metadata != null
+ && canLaunchInActivityView(getContext(), metadata.getIntent(), pkg);
// Does the app want to bubble & is able to bubble
- boolean canBubble = notification.getBubbleMetadata() != null
+ boolean canBubble = intentCanBubble
&& mPreferencesHelper.areBubblesAllowed(pkg, userId)
+ && mPreferencesHelper.bubblesEnabled(r.sbn.getUser())
&& r.getChannel().canBubble()
&& !mActivityManager.isLowRamDevice();
@@ -4869,6 +4878,63 @@ public class NotificationManagerService extends SystemService {
return false;
}
+ /**
+ * Whether an intent is properly configured to display in an {@link android.app.ActivityView}.
+ *
+ * @param context the context to use.
+ * @param pendingIntent the pending intent of the bubble.
+ * @param packageName the notification package name for this bubble.
+ */
+ // Keep checks in sync with BubbleController#canLaunchInActivityView.
+ @VisibleForTesting
+ protected boolean canLaunchInActivityView(Context context, PendingIntent pendingIntent,
+ String packageName) {
+ if (pendingIntent == null) {
+ Log.w(TAG, "Unable to create bubble -- no intent");
+ return false;
+ }
+
+ // Need escalated privileges to get the intent.
+ final long token = Binder.clearCallingIdentity();
+ Intent intent;
+ try {
+ intent = pendingIntent.getIntent();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
+ ActivityInfo info = intent != null
+ ? intent.resolveActivityInfo(context.getPackageManager(), 0)
+ : null;
+ if (info == null) {
+ StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName,
+ BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING);
+ Log.w(TAG, "Unable to send as bubble -- couldn't find activity info for intent: "
+ + intent);
+ return false;
+ }
+ if (!ActivityInfo.isResizeableMode(info.resizeMode)) {
+ StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName,
+ BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE);
+ Log.w(TAG, "Unable to send as bubble -- activity is not resizable for intent: "
+ + intent);
+ return false;
+ }
+ if (info.documentLaunchMode != DOCUMENT_LAUNCH_ALWAYS) {
+ StatsLog.write(StatsLog.BUBBLE_DEVELOPER_ERROR_REPORTED, packageName,
+ BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__DOCUMENT_LAUNCH_NOT_ALWAYS);
+ Log.w(TAG, "Unable to send as bubble -- activity is not documentLaunchMode=always "
+ + "for intent: " + intent);
+ return false;
+ }
+ if ((info.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
+ Log.w(TAG, "Unable to send as bubble -- activity is not embeddable for intent: "
+ + intent);
+ return false;
+ }
+ return true;
+ }
+
private void doChannelWarningToast(CharSequence toastText) {
Binder.withCleanCallingIdentity(() -> {
final int defaultWarningEnabled = Build.IS_DEBUGGABLE ? 1 : 0;
@@ -7344,7 +7410,7 @@ public class NotificationManagerService extends SystemService {
static final String TAG_ENABLED_NOTIFICATION_ASSISTANTS = "enabled_assistants";
private static final String ATT_USER_SET = "user_set";
- private static final String TAG_ALLOWED_ADJUSTMENT_TYPES = "allowed_adjustments";
+ private static final String TAG_ALLOWED_ADJUSTMENT_TYPES = "q_allowed_adjustments";
private static final String ATT_TYPES = "types";
private final Object mLock = new Object();
diff --git a/services/core/java/com/android/server/pm/ModuleInfoProvider.java b/services/core/java/com/android/server/pm/ModuleInfoProvider.java
index 6499530bd7c3..69510d9e5565 100644
--- a/services/core/java/com/android/server/pm/ModuleInfoProvider.java
+++ b/services/core/java/com/android/server/pm/ModuleInfoProvider.java
@@ -64,6 +64,7 @@ public class ModuleInfoProvider {
// TODO: Move this to an earlier boot phase if anybody requires it then.
private volatile boolean mMetadataLoaded;
+ private volatile String mPackageName;
ModuleInfoProvider(Context context, IPackageManager packageManager) {
mContext = context;
@@ -81,9 +82,9 @@ public class ModuleInfoProvider {
/** Called by the {@code PackageManager} when it has completed its boot sequence */
public void systemReady() {
- final String packageName = mContext.getResources().getString(
+ mPackageName = mContext.getResources().getString(
R.string.config_defaultModuleMetadataProvider);
- if (TextUtils.isEmpty(packageName)) {
+ if (TextUtils.isEmpty(mPackageName)) {
Slog.w(TAG, "No configured module metadata provider.");
return;
}
@@ -91,13 +92,13 @@ public class ModuleInfoProvider {
final Resources packageResources;
final PackageInfo pi;
try {
- pi = mPackageManager.getPackageInfo(packageName,
+ pi = mPackageManager.getPackageInfo(mPackageName,
PackageManager.GET_META_DATA, UserHandle.USER_SYSTEM);
- Context packageContext = mContext.createPackageContext(packageName, 0);
+ Context packageContext = mContext.createPackageContext(mPackageName, 0);
packageResources = packageContext.getResources();
} catch (RemoteException | NameNotFoundException e) {
- Slog.w(TAG, "Unable to discover metadata package: " + packageName, e);
+ Slog.w(TAG, "Unable to discover metadata package: " + mPackageName, e);
return;
}
@@ -201,4 +202,11 @@ public class ModuleInfoProvider {
return mModuleInfo.get(packageName);
}
+
+ String getPackageName() {
+ if (!mMetadataLoaded) {
+ throw new IllegalStateException("Call to getVersion before metadata loaded");
+ }
+ return mPackageName;
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index dd48e2dfa2c5..e86f56f90cb4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5646,9 +5646,11 @@ public class PackageManagerService extends IPackageManager.Stub
private int checkUidPermissionImpl(String permName, int uid) {
synchronized (mPackages) {
final String[] packageNames = getPackagesForUid(uid);
- final PackageParser.Package pkg = (packageNames != null && packageNames.length > 0)
- ? mPackages.get(packageNames[0])
- : null;
+ PackageParser.Package pkg = null;
+ final int N = packageNames == null ? 0 : packageNames.length;
+ for (int i = 0; pkg == null && i < N; i++) {
+ pkg = mPackages.get(packageNames[i]);
+ }
// Additional logs for b/111075456; ignore system UIDs
if (pkg == null && UserHandle.getAppId(uid) >= Process.FIRST_APPLICATION_UID) {
if (packageNames == null || packageNames.length < 2) {
@@ -6385,6 +6387,16 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
+ /**
+ * <em>IMPORTANT:</em> Not all packages returned by this method may be known
+ * to the system. There are two conditions in which this may occur:
+ * <ol>
+ * <li>The package is on adoptable storage and the device has been removed</li>
+ * <li>The package is being removed and the internal structures are partially updated</li>
+ * </ol>
+ * The second is an artifact of the current data structures and should be fixed. See
+ * b/111075456 for one such instance.
+ */
@Override
public String[] getPackagesForUid(int uid) {
return getPackagesForUid_debug(uid, false);
@@ -20921,6 +20933,12 @@ public class PackageManagerService extends IPackageManager.Stub
Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName()
+ " is holding mPackages", new Throwable());
}
+ if (!mSystemReady) {
+ // We might get called before system is ready because of package changes etc, but
+ // finding preferred activity depends on settings provider, so we ignore the update
+ // before that.
+ return false;
+ }
final Intent intent = getHomeIntent();
final List<ResolveInfo> resolveInfos = queryIntentActivitiesInternal(intent, null,
PackageManager.GET_META_DATA, userId);
@@ -24068,6 +24086,11 @@ public class PackageManagerService extends IPackageManager.Stub
| (appInfo.isVendor() ? IPackageManagerNative.LOCATION_VENDOR : 0)
| (appInfo.isProduct() ? IPackageManagerNative.LOCATION_PRODUCT : 0));
}
+
+ @Override
+ public String getModuleMetadataPackageName() throws RemoteException {
+ return PackageManagerService.this.mModuleInfoProvider.getPackageName();
+ }
}
private class PackageManagerInternalImpl extends PackageManagerInternal {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index b2ba2904cabc..2a1aee8a441c 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1347,6 +1347,7 @@ public class PermissionManagerService {
updatedUserIds);
updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origPermissions,
permissionsState, pkg, newImplicitPermissions, updatedUserIds);
+ updatedUserIds = checkIfLegacyStorageOpsNeedToBeUpdated(pkg, replace, updatedUserIds);
}
// Persist the runtime permissions state for users with changes. If permissions
@@ -1473,6 +1474,28 @@ public class PermissionManagerService {
}
/**
+ * When the app has requested legacy storage we might need to update
+ * {@link android.app.AppOpsManager#OP_LEGACY_STORAGE}. Hence force an update in
+ * {@link com.android.server.policy.PermissionPolicyService#synchronizePackagePermissionsAndAppOpsForUser(Context, String, int)}
+ *
+ * @param pkg The package for which the permissions are updated
+ * @param replace If the app is being replaced
+ * @param updatedUserIds The ids of the users that already changed.
+ *
+ * @return The ids of the users that are changed
+ */
+ private @NonNull int[] checkIfLegacyStorageOpsNeedToBeUpdated(
+ @NonNull PackageParser.Package pkg, boolean replace, @NonNull int[] updatedUserIds) {
+ if (replace && pkg.applicationInfo.hasRequestedLegacyExternalStorage() && (
+ pkg.requestedPermissions.contains(READ_EXTERNAL_STORAGE)
+ || pkg.requestedPermissions.contains(WRITE_EXTERNAL_STORAGE))) {
+ return UserManagerService.getInstance().getUserIds();
+ }
+
+ return updatedUserIds;
+ }
+
+ /**
* Set the state of a implicit permission that is seen for the first time.
*
* @param origPs The permission state of the package before the split
@@ -2091,7 +2114,7 @@ public class PermissionManagerService {
return;
}
- if (bp.isHardOrSoftRestricted()
+ if (bp.isHardRestricted()
&& (flags & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) == 0) {
Log.e(TAG, "Cannot grant restricted non-exempt permission "
+ permName + " for package " + packageName);
diff --git a/services/core/java/com/android/server/pm/permission/TEST_MAPPING b/services/core/java/com/android/server/pm/permission/TEST_MAPPING
index c27270712058..610c82f06843 100644
--- a/services/core/java/com/android/server/pm/permission/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/permission/TEST_MAPPING
@@ -18,6 +18,31 @@
]
},
{
+ "name": "CtsAppSecurityHostTestCases",
+ "options": [
+ {
+ "include-filter": "android.appsecurity.cts.AppSecurityTests#rebootWithDuplicatePermission"
+ }
+ ]
+ },
+ {
+ "name": "CtsPermission2TestCases",
+ "options": [
+ {
+ "include-filter": "android.permission.cts.SharedUidPermissionsTest"
+ },
+ {
+ "include-filter": "android.permission.cts.RestrictedPermissionsTest"
+ },
+ {
+ "include-filter": "android.permission.cts.PermissionMaxSdkVersionTest"
+ },
+ {
+ "include-filter": "android.permission.cts.PrivappPermissionsTest"
+ }
+ ]
+ },
+ {
"name": "CtsStatsdHostTestCases",
"options": [
{
@@ -25,5 +50,15 @@
}
]
}
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsAppSecurityHostTestCases",
+ "options": [
+ {
+ "include-filter": "android.appsecurity.cts.AppSecurityTests#testPermissionDiffCert"
+ }
+ ]
+ }
]
}
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyInternal.java b/services/core/java/com/android/server/policy/PermissionPolicyInternal.java
index ea8616c4551b..7760c1edd9e6 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyInternal.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyInternal.java
@@ -17,6 +17,7 @@
package com.android.server.policy;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Intent;
/**
@@ -34,5 +35,5 @@ public abstract class PermissionPolicyInternal {
* @return whether the activity should be started
*/
public abstract boolean checkStartActivity(@NonNull Intent intent, int callingUid,
- @NonNull String callingPackage);
+ @Nullable String callingPackage);
}
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 570a15310089..02911e272692 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -229,6 +229,15 @@ public final class PermissionPolicyService extends SystemService {
*
* @see #syncRestrictedOps
*/
+ private final @NonNull ArrayList<OpToUnrestrict> mOpsToAllowIfDefault = new ArrayList<>();
+
+ /**
+ * All ops that need to be flipped to allow.
+ *
+ * Currently, only used by the restricted permissions logic.
+ *
+ * @see #syncRestrictedOps
+ */
private final @NonNull ArrayList<OpToUnrestrict> mOpsToAllow = new ArrayList<>();
/**
@@ -238,7 +247,7 @@ public final class PermissionPolicyService extends SystemService {
*
* @see #syncRestrictedOps
*/
- private final @NonNull ArrayList<OpToUnrestrict> mOpsToIgnore = new ArrayList<>();
+ private final @NonNull ArrayList<OpToUnrestrict> mOpsToIgnoreIfDefault = new ArrayList<>();
/**
* All foreground permissions
@@ -262,11 +271,16 @@ public final class PermissionPolicyService extends SystemService {
final int allowCount = mOpsToAllow.size();
for (int i = 0; i < allowCount; i++) {
final OpToUnrestrict op = mOpsToAllow.get(i);
+ setUidModeAllowed(op.code, op.uid);
+ }
+ final int allowIfDefaultCount = mOpsToAllowIfDefault.size();
+ for (int i = 0; i < allowIfDefaultCount; i++) {
+ final OpToUnrestrict op = mOpsToAllowIfDefault.get(i);
setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
}
- final int ignoreCount = mOpsToIgnore.size();
- for (int i = 0; i < ignoreCount; i++) {
- final OpToUnrestrict op = mOpsToIgnore.get(i);
+ final int ignoreIfDefaultCount = mOpsToIgnoreIfDefault.size();
+ for (int i = 0; i < ignoreIfDefaultCount; i++) {
+ final OpToUnrestrict op = mOpsToIgnoreIfDefault.get(i);
setUidModeIgnoredIfDefault(op.code, op.uid, op.packageName);
}
final int defaultCount = mOpsToDefault.size();
@@ -341,7 +355,7 @@ public final class PermissionPolicyService extends SystemService {
if (applyRestriction) {
mOpsToDefault.add(new OpToRestrict(uid, opCode));
} else {
- mOpsToAllow.add(new OpToUnrestrict(uid, pkg.packageName, opCode));
+ mOpsToAllowIfDefault.add(new OpToUnrestrict(uid, pkg.packageName, opCode));
}
} else if (permissionInfo.isSoftRestricted()) {
// Storage uses a special app op to decide the mount state and
@@ -356,7 +370,7 @@ public final class PermissionPolicyService extends SystemService {
mOpsToAllow.add(new OpToUnrestrict(uid, pkg.packageName,
AppOpsManager.OP_LEGACY_STORAGE));
} else {
- mOpsToIgnore.add(new OpToUnrestrict(uid, pkg.packageName,
+ mOpsToIgnoreIfDefault.add(new OpToUnrestrict(uid, pkg.packageName,
AppOpsManager.OP_LEGACY_STORAGE));
}
}
@@ -421,6 +435,10 @@ public final class PermissionPolicyService extends SystemService {
setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_ALLOWED, packageName);
}
+ private void setUidModeAllowed(int opCode, int uid) {
+ mAppOpsManager.setUidMode(opCode, uid, AppOpsManager.MODE_ALLOWED);
+ }
+
private void setUidModeIgnoredIfDefault(int opCode, int uid, @NonNull String packageName) {
setUidModeIfDefault(opCode, uid, AppOpsManager.MODE_IGNORED, packageName);
}
@@ -480,8 +498,9 @@ public final class PermissionPolicyService extends SystemService {
@Override
public boolean checkStartActivity(@NonNull Intent intent, int callingUid,
- @NonNull String callingPackage) {
- if (isActionRemovedForCallingPackage(intent.getAction(), callingPackage)) {
+ @Nullable String callingPackage) {
+ if (callingPackage != null && isActionRemovedForCallingPackage(intent.getAction(),
+ callingPackage)) {
Slog.w(LOG_TAG, "Action Removed: starting " + intent.toString() + " from "
+ callingPackage + " (uid=" + callingUid + ")");
return false;
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 944e4b83841c..9a2778dbf535 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -231,6 +231,20 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
}
}, enableRollbackTimedOutFilter, null, getHandler());
+ IntentFilter userAddedIntentFilter = new IntentFilter(Intent.ACTION_USER_ADDED);
+ mContext.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) {
+ final int newUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+ if (newUserId == -1) {
+ return;
+ }
+ registerUserCallbacks(UserHandle.of(newUserId));
+ }
+ }
+ }, userAddedIntentFilter, null, getHandler());
+
registerTimeChangeReceiver();
}
diff --git a/services/core/java/com/android/server/rollback/TEST_MAPPING b/services/core/java/com/android/server/rollback/TEST_MAPPING
index 921b75478d13..8c7b5acf5c3a 100644
--- a/services/core/java/com/android/server/rollback/TEST_MAPPING
+++ b/services/core/java/com/android/server/rollback/TEST_MAPPING
@@ -14,5 +14,13 @@
}
]
}
+ ],
+ "imports": [
+ {
+ "path": "cts/tests/rollback"
+ },
+ {
+ "path": "cts/hostsidetests/rollback"
+ }
]
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 7734d6bd30a7..a93d2b8b6fb9 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -108,4 +108,9 @@ public interface StatusBarManagerInternal {
* @param displayId display ID
*/
void onDisplayReady(int displayId);
+
+ /**
+ * Notifies System UI whether the recents animation is running.
+ */
+ void onRecentsAnimationStateChanged(boolean running);
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index b2d7084fcd05..112104d073b0 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -453,8 +453,18 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
if (mBar != null) {
try {
mBar.onDisplayReady(displayId);
- } catch (RemoteException ex) { }
+ } catch (RemoteException ex) {}
+ }
+ }
+
+ @Override
+ public void onRecentsAnimationStateChanged(boolean running) {
+ if (mBar != null) {
+ try {
+ mBar.onRecentsAnimationStateChanged(running);
+ } catch (RemoteException ex) {}
}
+
}
};
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 332df956d0fb..8b332d271a3a 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -211,9 +211,9 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
}
@Override
- public ParceledListSlice<android.content.UriPermission> getPersistedUriPermissions(
- String packageName, boolean incoming) {
- enforceNotIsolatedCaller("getPersistedUriPermissions");
+ public ParceledListSlice<android.content.UriPermission> getUriPermissions(
+ String packageName, boolean incoming, boolean persistedOnly) {
+ enforceNotIsolatedCaller("getUriPermissions");
Preconditions.checkNotNull(packageName, "packageName");
final int callingUid = Binder.getCallingUid();
@@ -240,7 +240,8 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
} else {
for (int j = 0; j < perms.size(); j++) {
final UriPermission perm = perms.valueAt(j);
- if (packageName.equals(perm.targetPkg) && perm.persistedModeFlags != 0) {
+ if (packageName.equals(perm.targetPkg)
+ && (!persistedOnly || perm.persistedModeFlags != 0)) {
result.add(perm.buildPersistedPublicApiObject());
}
}
@@ -252,7 +253,8 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
mGrantedUriPermissions.valueAt(i);
for (int j = 0; j < perms.size(); j++) {
final UriPermission perm = perms.valueAt(j);
- if (packageName.equals(perm.sourcePkg) && perm.persistedModeFlags != 0) {
+ if (packageName.equals(perm.sourcePkg)
+ && (!persistedOnly || perm.persistedModeFlags != 0)) {
result.add(perm.buildPersistedPublicApiObject());
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 66b305ec2dac..1344727ab36d 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1085,22 +1085,6 @@ final class ActivityRecord extends ConfigurationContainer {
if (root == this) {
task.setRootProcess(proc);
}
- // Override the process configuration to match the display where the first activity in
- // the process was launched. This can help with compat issues on secondary displays when
- // apps use Application to obtain configuration or metrics instead of Activity.
- final ActivityDisplay display = getDisplay();
- if (display == null || display.mDisplayId == INVALID_DISPLAY) {
- return;
- }
- if (!proc.hasActivities() && display.mDisplayId != DEFAULT_DISPLAY) {
- proc.registerDisplayConfigurationListenerLocked(display);
- } else if (display.mDisplayId == DEFAULT_DISPLAY) {
- // Once an activity is launched on default display - stop listening for other displays
- // configurations to maintain compatibility with previous platform releases. E.g. when
- // an activity is launched in a Bubble and then moved to default screen, we should match
- // the global device config.
- proc.unregisterDisplayConfigurationListenerLocked();
- }
}
boolean hasProcess() {
@@ -3249,7 +3233,7 @@ final class ActivityRecord extends ConfigurationContainer {
// Update last reported values.
final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
- setLastReportedConfiguration(getProcessGlobalConfiguration(), newMergedOverrideConfig);
+ setLastReportedConfiguration(mAtmService.getGlobalConfiguration(), newMergedOverrideConfig);
if (mState == INITIALIZING) {
// No need to relaunch or schedule new config for activity that hasn't been launched
@@ -3358,14 +3342,6 @@ final class ActivityRecord extends ConfigurationContainer {
return true;
}
- /** Get process configuration, or global config if the process is not set. */
- private Configuration getProcessGlobalConfiguration() {
- if (app != null) {
- return app.getConfiguration();
- }
- return mAtmService.getGlobalConfiguration();
- }
-
/**
* When assessing a configuration change, decide if the changes flags and the new configurations
* should cause the Activity to relaunch.
@@ -3473,7 +3449,7 @@ final class ActivityRecord extends ConfigurationContainer {
mStackSupervisor.activityRelaunchingLocked(this);
final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
pendingNewIntents, configChangeFlags,
- new MergedConfiguration(getProcessGlobalConfiguration(),
+ new MergedConfiguration(mAtmService.getGlobalConfiguration(),
getMergedOverrideConfiguration()),
preserveWindow);
final ActivityLifecycleItem lifecycleItem;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 82ea4fe42799..c3a769b63e5a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -804,10 +804,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mTmpApplySurfaceChangesTransactionState.preferredRefreshRate
= w.mAttrs.preferredRefreshRate;
}
+ final int preferredModeId = getDisplayPolicy().getRefreshRatePolicy()
+ .getPreferredModeId(w);
if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0
- && w.mAttrs.preferredDisplayModeId != 0) {
- mTmpApplySurfaceChangesTransactionState.preferredModeId
- = w.mAttrs.preferredDisplayModeId;
+ && preferredModeId != 0) {
+ mTmpApplySurfaceChangesTransactionState.preferredModeId = preferredModeId;
}
}
}
@@ -2636,17 +2637,25 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
final WindowState imeWin = mInputMethodWindow;
final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
&& !mDividerControllerLocked.isImeHideRequested();
- final boolean dockVisible = isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ final TaskStack dockedStack = getSplitScreenPrimaryStack();
+ final boolean dockVisible = dockedStack != null;
+ final Task topDockedTask = dockVisible ? dockedStack.getTopChild() : null;
final TaskStack imeTargetStack = mWmService.getImeFocusStackLocked();
final int imeDockSide = (dockVisible && imeTargetStack != null) ?
imeTargetStack.getDockSide() : DOCKED_INVALID;
final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
- final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock();
final int imeHeight = mDisplayFrames.getInputMethodWindowVisibleHeight();
final boolean imeHeightChanged = imeVisible &&
imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor();
+ // This includes a case where the docked stack is unminimizing and IME is visible for the
+ // bottom side stack. The condition prevents adjusting the override task bounds for IME to
+ // the minimized docked stack bounds.
+ final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock()
+ || (topDockedTask != null && imeOnBottom && !dockedStack.isAdjustedForIme()
+ && dockedStack.getBounds().height() < topDockedTask.getBounds().height());
+
// The divider could be adjusted for IME position, or be thinner than usual,
// or both. There are three possible cases:
// - If IME is visible, and focus is on top, divider is not moved for IME but thinner.
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 197a3cf2b3ab..e1dd3522a808 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -381,6 +381,8 @@ public class DisplayPolicy {
*/
@NonNull private Insets mForwardedInsets = Insets.NONE;
+ private RefreshRatePolicy mRefreshRatePolicy;
+
// -------- PolicyHandler --------
private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 1;
private static final int MSG_REQUEST_TRANSIENT_BARS = 2;
@@ -591,6 +593,10 @@ public class DisplayPolicy {
mHasStatusBar = false;
mHasNavigationBar = mDisplayContent.supportsSystemDecorations();
}
+
+ mRefreshRatePolicy = new RefreshRatePolicy(mService,
+ mDisplayContent.getDisplayInfo(),
+ mService.mHighRefreshRateBlacklist);
}
void systemReady() {
@@ -3596,6 +3602,10 @@ public class DisplayPolicy {
}
}
+ RefreshRatePolicy getRefreshRatePolicy() {
+ return mRefreshRatePolicy;
+ }
+
void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("DisplayPolicy");
prefix += " ";
diff --git a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
new file mode 100644
index 000000000000..c0f53b819125
--- /dev/null
+++ b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.annotation.NonNull;
+import android.os.SystemProperties;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * A Blacklist for packages that should force the display out of high refresh rate.
+ */
+class HighRefreshRateBlacklist {
+
+ private static final String SYSPROP_KEY = "ro.window_manager.high_refresh_rate_blacklist";
+ private static final String SYSPROP_KEY_LENGTH_SUFFIX = "_length";
+ private static final String SYSPROP_KEY_ENTRY_SUFFIX = "_entry";
+ private static final int MAX_ENTRIES = 50;
+
+ private ArraySet<String> mBlacklistedPackages = new ArraySet<>();
+
+ static HighRefreshRateBlacklist create() {
+ return new HighRefreshRateBlacklist(new SystemPropertyGetter() {
+ @Override
+ public int getInt(String key, int def) {
+ return SystemProperties.getInt(key, def);
+ }
+
+ @Override
+ public String get(String key) {
+ return SystemProperties.get(key);
+ }
+ });
+ }
+
+ @VisibleForTesting
+ HighRefreshRateBlacklist(SystemPropertyGetter propertyGetter) {
+
+ // Read and populate the blacklist
+ final int length = Math.min(
+ propertyGetter.getInt(SYSPROP_KEY + SYSPROP_KEY_LENGTH_SUFFIX, 0),
+ MAX_ENTRIES);
+ for (int i = 1; i <= length; i++) {
+ final String packageName = propertyGetter.get(
+ SYSPROP_KEY + SYSPROP_KEY_ENTRY_SUFFIX + i);
+ if (!packageName.isEmpty()) {
+ mBlacklistedPackages.add(packageName);
+ }
+ }
+ }
+
+ boolean isBlacklisted(String packageName) {
+ return mBlacklistedPackages.contains(packageName);
+ }
+
+ interface SystemPropertyGetter {
+ int getInt(String key, int def);
+ @NonNull String get(String key);
+ }
+}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index d2c510fa8902..c03dabe660ad 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -56,6 +56,7 @@ import android.view.SurfaceControl.Transaction;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import com.android.server.inputmethod.InputMethodManagerInternal;
+import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
import com.android.server.wm.utils.InsetUtils;
@@ -87,6 +88,7 @@ public class RecentsAnimationController implements DeathRecipient {
public @interface ReorderMode {}
private final WindowManagerService mService;
+ private final StatusBarManagerInternal mStatusBar;
private IRecentsAnimationRunner mRunner;
private final RecentsAnimationCallbacks mCallbacks;
private final ArrayList<TaskAnimationAdapter> mPendingAnimations = new ArrayList<>();
@@ -308,6 +310,7 @@ public class RecentsAnimationController implements DeathRecipient {
mRunner = remoteAnimationRunner;
mCallbacks = callbacks;
mDisplayId = displayId;
+ mStatusBar = LocalServices.getService(StatusBarManagerInternal.class);
}
public void initialize(int targetActivityType, SparseBooleanArray recentTaskIds) {
@@ -381,6 +384,9 @@ public class RecentsAnimationController implements DeathRecipient {
mMinimizedHomeBounds);
mService.mWindowPlacerLocked.performSurfacePlacement();
+
+ // Notify that the animation has started
+ mStatusBar.onRecentsAnimationStateChanged(true /* running */);
}
@VisibleForTesting
@@ -594,6 +600,9 @@ public class RecentsAnimationController implements DeathRecipient {
.mAppTransition.notifyAppTransitionFinishedLocked(mTargetAppToken.token);
}
}
+
+ // Notify that the animation has ended
+ mStatusBar.onRecentsAnimationStateChanged(false /* running */);
}
void scheduleFailsafe() {
diff --git a/services/core/java/com/android/server/wm/RefreshRatePolicy.java b/services/core/java/com/android/server/wm/RefreshRatePolicy.java
new file mode 100644
index 000000000000..0c0cf9262e44
--- /dev/null
+++ b/services/core/java/com/android/server/wm/RefreshRatePolicy.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.util.ArraySet;
+import android.view.Display.Mode;
+import android.view.DisplayInfo;
+
+/**
+ * Policy to select a lower refresh rate for the display if applicable.
+ */
+class RefreshRatePolicy {
+
+ private final int mLowRefreshRateId;
+ private final ArraySet<String> mNonHighRefreshRatePackages = new ArraySet<>();
+ private final HighRefreshRateBlacklist mHighRefreshRateBlacklist;
+ private final WindowManagerService mWmService;
+
+ RefreshRatePolicy(WindowManagerService wmService, DisplayInfo displayInfo,
+ HighRefreshRateBlacklist blacklist) {
+ mLowRefreshRateId = findLowRefreshRateModeId(displayInfo);
+ mHighRefreshRateBlacklist = blacklist;
+ mWmService = wmService;
+ }
+
+ /**
+ * Finds the mode id with the lowest refresh rate which is >= 60hz and same resolution as the
+ * default mode.
+ */
+ private int findLowRefreshRateModeId(DisplayInfo displayInfo) {
+ Mode mode = displayInfo.getDefaultMode();
+ float[] refreshRates = displayInfo.getDefaultRefreshRates();
+ float bestRefreshRate = mode.getRefreshRate();
+ for (int i = refreshRates.length - 1; i >= 0; i--) {
+ if (refreshRates[i] >= 60f && refreshRates[i] < bestRefreshRate) {
+ bestRefreshRate = refreshRates[i];
+ }
+ }
+ return displayInfo.findDefaultModeByRefreshRate(bestRefreshRate);
+ }
+
+ void addNonHighRefreshRatePackage(String packageName) {
+ mNonHighRefreshRatePackages.add(packageName);
+ mWmService.requestTraversal();
+ }
+
+ void removeNonHighRefreshRatePackage(String packageName) {
+ mNonHighRefreshRatePackages.remove(packageName);
+ mWmService.requestTraversal();
+ }
+
+ int getPreferredModeId(WindowState w) {
+
+ // If app is animating, it's not able to control refresh rate because we want the animation
+ // to run in default refresh rate.
+ if (w.isAnimating()) {
+ return 0;
+ }
+
+ // If app requests a certain refresh rate or mode, don't override it.
+ if (w.mAttrs.preferredRefreshRate != 0 || w.mAttrs.preferredDisplayModeId != 0) {
+ return w.mAttrs.preferredDisplayModeId;
+ }
+
+ final String packageName = w.getOwningPackage();
+
+ // If app is using Camera, force it to default (lower) refresh rate.
+ if (mNonHighRefreshRatePackages.contains(packageName)) {
+ return mLowRefreshRateId;
+ }
+
+ // If app is blacklisted using higher refresh rate, return default (lower) refresh rate
+ if (mHighRefreshRateBlacklist.isBlacklisted(packageName)) {
+ return mLowRefreshRateId;
+ }
+ return 0;
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 75a8dd53d2e6..40bec148b33b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -492,4 +492,18 @@ public abstract class WindowManagerInternal {
* @return {@code true} if the display should show IME when an input field become focused on it.
*/
public abstract boolean shouldShowIme(int displayId);
+
+ /**
+ * Tell window manager about a package that should not be running with high refresh rate
+ * setting until removeNonHighRefreshRatePackage is called for the same package.
+ *
+ * This must not be called again for the same package.
+ */
+ public abstract void addNonHighRefreshRatePackage(@NonNull String packageName);
+
+ /**
+ * Tell window manager to stop constraining refresh rate for the given package.
+ */
+ public abstract void removeNonHighRefreshRatePackage(@NonNull String packageName);
+
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 47df83923700..d39ee4068285 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -845,6 +845,8 @@ public class WindowManagerService extends IWindowManager.Stub
final Configuration mTempConfiguration = new Configuration();
+ final HighRefreshRateBlacklist mHighRefreshRateBlacklist = HighRefreshRateBlacklist.create();
+
// If true, only the core apps and services are being launched because the device
// is in a special boot mode, such as being encrypted or waiting for a decryption password.
// For example, when this flag is true, there will be no wallpaper service.
@@ -7446,6 +7448,22 @@ public class WindowManagerService extends IWindowManager.Stub
return WindowManagerService.this.shouldShowIme(displayId);
}
}
+
+ @Override
+ public void addNonHighRefreshRatePackage(@NonNull String packageName) {
+ synchronized (mGlobalLock) {
+ mRoot.forAllDisplays(dc -> dc.getDisplayPolicy().getRefreshRatePolicy()
+ .addNonHighRefreshRatePackage(packageName));
+ }
+ }
+
+ @Override
+ public void removeNonHighRefreshRatePackage(@NonNull String packageName) {
+ synchronized (mGlobalLock) {
+ mRoot.forAllDisplays(dc -> dc.getDisplayPolicy().getRefreshRatePolicy()
+ .removeNonHighRefreshRatePackage(packageName));
+ }
+ }
}
void registerAppFreezeListener(AppFreezeListener listener) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 5fc399719aed..12b62b99b3e2 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -439,10 +439,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
@Override
protected ConfigurationContainer getParent() {
- // Returning RootActivityContainer as the parent, so that this process controller always
- // has full configuration and overrides (e.g. from display) are always added on top of
- // global config.
- return mAtm.mRootActivityContainer;
+ return null;
}
@HotPath(caller = HotPath.PROCESS_CHANGE)
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c35e86645719..5ef184adc52f 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3104,7 +3104,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
+ ": " + mWindowFrames.mCompatFrame);
final MergedConfiguration mergedConfiguration =
- new MergedConfiguration(getProcessGlobalConfiguration(),
+ new MergedConfiguration(mWmService.mRoot.getConfiguration(),
getMergedOverrideConfiguration());
setLastReportedMergedConfiguration(mergedConfiguration);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index e2e9c420a046..e1aeb33445ed 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -108,6 +108,8 @@ import android.app.ActivityTaskManager;
import android.app.ActivityThread;
import android.app.AlarmManager;
import android.app.AppGlobals;
+import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
import android.app.IActivityManager;
import android.app.IActivityTaskManager;
import android.app.IApplicationThread;
@@ -2897,12 +2899,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
admin.getUserHandle()).isEmpty()) {
return false;
}
+
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setBackgroundActivityStartsAllowed(true);
+
if (result != null) {
mContext.sendOrderedBroadcastAsUser(intent, admin.getUserHandle(),
- null, result, mHandler, Activity.RESULT_OK, null, null);
+ null, AppOpsManager.OP_NONE, options.toBundle(),
+ result, mHandler, Activity.RESULT_OK, null, null);
} else {
- mContext.sendBroadcastAsUser(intent, admin.getUserHandle());
+ mContext.sendBroadcastAsUser(intent, admin.getUserHandle(), null, options.toBundle());
}
+
return true;
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index e42ed3b03139..4e1cac905178 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -36,6 +36,7 @@ import android.content.res.Configuration;
import android.content.res.Resources.Theme;
import android.database.sqlite.SQLiteCompatibilityWalFlags;
import android.database.sqlite.SQLiteGlobal;
+import android.hardware.display.DisplayManagerInternal;
import android.net.NetworkStackClient;
import android.os.BaseBundle;
import android.os.Binder;
@@ -790,6 +791,12 @@ public final class SystemServer {
mSystemServiceManager.startService(new SensorPrivacyService(mSystemContext));
traceEnd();
+ if (SystemProperties.getInt("persist.sys.displayinset.top", 0) > 0) {
+ // DisplayManager needs the overlay immediately.
+ mActivityManagerService.updateSystemUiContext();
+ LocalServices.getService(DisplayManagerInternal.class).onOverlayChanged();
+ }
+
// The sensor service needs access to package manager service, app ops
// service, and permissions service, therefore we start it after them.
// Start sensor service in a separate thread. Completion should be checked
diff --git a/services/net/Android.bp b/services/net/Android.bp
index ab11fe4df283..fb548f9975c5 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -19,6 +19,7 @@ aidl_interface {
versions: [
"1",
"2",
+ "3",
],
}
@@ -64,10 +65,10 @@ java_library_static {
name: "services.net",
srcs: ["java/**/*.java"],
static_libs: [
- "dnsresolver_aidl_interface-java",
+ "dnsresolver_aidl_interface-V2-java",
"ipmemorystore-client",
- "netd_aidl_interface-java",
- "networkstack-aidl-interfaces-java",
+ "netd_aidl_interface-V2-java",
+ "networkstack-aidl-interfaces-V3-java",
],
}
@@ -80,7 +81,7 @@ java_library_static {
"java/android/net/ipmemorystore/**/*.java",
],
static_libs: [
- "ipmemorystore-aidl-interfaces-java",
+ "ipmemorystore-aidl-interfaces-V3-java",
],
}
diff --git a/services/net/aidl/ipmemorystore/3/android/net/IIpMemoryStore.aidl b/services/net/aidl/ipmemorystore/3/android/net/IIpMemoryStore.aidl
new file mode 100644
index 000000000000..1e688d0874de
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/3/android/net/IIpMemoryStore.aidl
@@ -0,0 +1,10 @@
+package android.net;
+interface IIpMemoryStore {
+ oneway void storeNetworkAttributes(String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnStatusListener listener);
+ oneway void storeBlob(String l2Key, String clientId, String name, in android.net.ipmemorystore.Blob data, android.net.ipmemorystore.IOnStatusListener listener);
+ oneway void findL2Key(in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnL2KeyResponseListener listener);
+ oneway void isSameNetwork(String l2Key1, String l2Key2, android.net.ipmemorystore.IOnSameL3NetworkResponseListener listener);
+ oneway void retrieveNetworkAttributes(String l2Key, android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener listener);
+ oneway void retrieveBlob(String l2Key, String clientId, String name, android.net.ipmemorystore.IOnBlobRetrievedListener listener);
+ oneway void factoryReset();
+}
diff --git a/services/net/aidl/ipmemorystore/3/android/net/IIpMemoryStoreCallbacks.aidl b/services/net/aidl/ipmemorystore/3/android/net/IIpMemoryStoreCallbacks.aidl
new file mode 100644
index 000000000000..cf02c26c2fe3
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/3/android/net/IIpMemoryStoreCallbacks.aidl
@@ -0,0 +1,4 @@
+package android.net;
+interface IIpMemoryStoreCallbacks {
+ oneway void onIpMemoryStoreFetched(in android.net.IIpMemoryStore ipMemoryStore);
+}
diff --git a/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/Blob.aidl b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/Blob.aidl
new file mode 100644
index 000000000000..291dbef817e6
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/Blob.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+parcelable Blob {
+ byte[] data;
+}
diff --git a/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
new file mode 100644
index 000000000000..52f40d49abd5
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnBlobRetrievedListener {
+ oneway void onBlobRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in String name, in android.net.ipmemorystore.Blob data);
+}
diff --git a/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
new file mode 100644
index 000000000000..785351435d73
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnL2KeyResponseListener {
+ oneway void onL2KeyResponse(in android.net.ipmemorystore.StatusParcelable status, in String l2Key);
+}
diff --git a/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
new file mode 100644
index 000000000000..3dd2ae6e9bab
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnNetworkAttributesRetrievedListener {
+ oneway void onNetworkAttributesRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes);
+}
diff --git a/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
new file mode 100644
index 000000000000..46d4ecb9ed7c
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnSameL3NetworkResponseListener {
+ oneway void onSameL3NetworkResponse(in android.net.ipmemorystore.StatusParcelable status, in android.net.ipmemorystore.SameL3NetworkResponseParcelable response);
+}
diff --git a/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnStatusListener.aidl b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnStatusListener.aidl
new file mode 100644
index 000000000000..54e654b80c9e
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnStatusListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnStatusListener {
+ oneway void onComplete(in android.net.ipmemorystore.StatusParcelable status);
+}
diff --git a/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/NetworkAttributesParcelable.aidl b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
new file mode 100644
index 000000000000..9531ea3963fb
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
@@ -0,0 +1,8 @@
+package android.net.ipmemorystore;
+parcelable NetworkAttributesParcelable {
+ byte[] assignedV4Address;
+ long assignedV4AddressExpiry;
+ String groupHint;
+ android.net.ipmemorystore.Blob[] dnsAddresses;
+ int mtu;
+}
diff --git a/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
new file mode 100644
index 000000000000..414272b49f1d
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
@@ -0,0 +1,6 @@
+package android.net.ipmemorystore;
+parcelable SameL3NetworkResponseParcelable {
+ String l2Key1;
+ String l2Key2;
+ float confidence;
+}
diff --git a/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/StatusParcelable.aidl b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/StatusParcelable.aidl
new file mode 100644
index 000000000000..92c6779b5dc0
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/3/android/net/ipmemorystore/StatusParcelable.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+parcelable StatusParcelable {
+ int resultCode;
+}
diff --git a/services/net/java/android/net/IIpMemoryStore.aidl b/services/net/java/android/net/IIpMemoryStore.aidl
index 63feae65756f..add221ae2e01 100644
--- a/services/net/java/android/net/IIpMemoryStore.aidl
+++ b/services/net/java/android/net/IIpMemoryStore.aidl
@@ -110,4 +110,9 @@ oneway interface IIpMemoryStore {
*/
void retrieveBlob(String l2Key, String clientId, String name,
IOnBlobRetrievedListener listener);
+
+ /**
+ * Delete all data because a factory reset operation is in progress.
+ */
+ void factoryReset();
}
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 1522a60850a1..869913dec646 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -73,7 +73,7 @@ android_test {
"libui",
"libunwindstack",
"libutils",
- "netd_aidl_interface-cpp",
+ "netd_aidl_interface-V2-cpp",
],
dxflags: ["--multi-dex"],
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index cbabb0b350d1..9ae9824da3e2 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -57,6 +57,7 @@ import static org.testng.Assert.assertThrows;
import android.Manifest.permission;
import android.annotation.RawRes;
import android.app.Activity;
+import android.app.AppOpsManager;
import android.app.Notification;
import android.app.admin.DeviceAdminReceiver;
import android.app.admin.DevicePolicyManager;
@@ -379,7 +380,9 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(mContext.spiedContext).sendBroadcastAsUser(
MockUtils.checkIntentAction(
DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED),
- MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
+ MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE),
+ eq(null),
+ any(Bundle.class));
verify(getServices().ipackageManager, times(1)).setApplicationEnabledSetting(
eq(admin1.getPackageName()),
@@ -657,6 +660,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED),
MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE),
isNull(String.class),
+ eq(AppOpsManager.OP_NONE),
+ any(Bundle.class),
any(BroadcastReceiver.class),
eq(dpms.mHandler),
eq(Activity.RESULT_OK),
@@ -707,6 +712,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED),
MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE),
isNull(String.class),
+ eq(AppOpsManager.OP_NONE),
+ any(Bundle.class),
any(BroadcastReceiver.class),
eq(dpms.mHandler),
eq(Activity.RESULT_OK),
@@ -788,10 +795,14 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
MockUtils.checkIntent(intent),
- MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
+ MockUtils.checkUserHandle(UserHandle.USER_SYSTEM),
+ eq(null),
+ any(Bundle.class));
verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
MockUtils.checkIntent(intent),
- MockUtils.checkUserHandle(MANAGED_PROFILE_USER_ID));
+ MockUtils.checkUserHandle(MANAGED_PROFILE_USER_ID),
+ eq(null),
+ any(Bundle.class));
}
/**
@@ -828,10 +839,14 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(mContext.spiedContext, never()).sendBroadcastAsUser(
MockUtils.checkIntent(intent),
- MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
+ MockUtils.checkUserHandle(UserHandle.USER_SYSTEM),
+ eq(null),
+ any(Bundle.class));
verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
MockUtils.checkIntent(intent),
- MockUtils.checkUserHandle(MANAGED_PROFILE_USER_ID));
+ MockUtils.checkUserHandle(MANAGED_PROFILE_USER_ID),
+ eq(null),
+ any(Bundle.class));
}
/**
@@ -4298,7 +4313,9 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
MockUtils.checkIntent(intent),
- MockUtils.checkUserHandle(userHandle));
+ MockUtils.checkUserHandle(userHandle),
+ eq(null),
+ any());
// CertificateMonitor.updateInstalledCertificates is called on the background thread,
// let it finish with system uid, otherwise it will throw and crash.
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index e411fb5d893f..bd513dc083be 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -18,6 +18,8 @@ package com.android.server.devicepolicy;
import static org.mockito.Mockito.mock;
+import android.annotation.Nullable;
+import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -324,6 +326,12 @@ public class DpmMockContext extends MockContext {
}
@Override
+ public void sendBroadcastAsUser(Intent intent,
+ UserHandle user, @Nullable String receiverPermission, @Nullable Bundle options) {
+ spiedContext.sendBroadcastAsUser(intent, user, receiverPermission, options);
+ }
+
+ @Override
public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission) {
spiedContext.sendBroadcastAsUser(intent, user, receiverPermission);
}
@@ -338,17 +346,17 @@ public class DpmMockContext extends MockContext {
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
int initialCode, String initialData, Bundle initialExtras) {
- spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, resultReceiver,
+ sendOrderedBroadcastAsUser(
+ intent, user, receiverPermission, AppOpsManager.OP_NONE, resultReceiver,
scheduler, initialCode, initialData, initialExtras);
- resultReceiver.onReceive(spiedContext, intent);
}
@Override
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
- spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp,
- resultReceiver,
+ sendOrderedBroadcastAsUser(
+ intent, user, receiverPermission, appOp, null, resultReceiver,
scheduler, initialCode, initialData, initialExtras);
}
@@ -358,6 +366,7 @@ public class DpmMockContext extends MockContext {
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, options,
resultReceiver, scheduler, initialCode, initialData, initialExtras);
+ resultReceiver.onReceive(spiedContext, intent);
}
@Override
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 92198fa8cb0c..4a9cef1f1cbd 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -55,6 +55,6 @@ android_test {
"libui",
"libunwindstack",
"libutils",
- "netd_aidl_interface-cpp",
+ "netd_aidl_interface-V2-cpp",
],
}
diff --git a/services/tests/uiservicestests/AndroidManifest.xml b/services/tests/uiservicestests/AndroidManifest.xml
index 3ff85c8806ce..7453c489ecc8 100644
--- a/services/tests/uiservicestests/AndroidManifest.xml
+++ b/services/tests/uiservicestests/AndroidManifest.xml
@@ -30,12 +30,14 @@
<uses-permission android:name="android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" />
+ <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT"/>
<application android:debuggable="true">
<uses-library android:name="android.test.runner" />
<provider android:name=".DummyProvider"
android:authorities="com.android.services.uitests" />
+
</application>
<instrumentation
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 3661e89a5d00..87f221a18161 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -304,6 +304,12 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
void onGranted(ComponentName assistant, int userId, boolean granted);
}
+ @Override
+ protected boolean canLaunchInActivityView(Context context, PendingIntent pendingIntent,
+ String packageName) {
+ // Tests for this not being true are in CTS NotificationManagerTest
+ return true;
+ }
}
private class TestableToastCallback extends ITransientNotification.Stub {
@@ -412,6 +418,19 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mTestableLooper.processAllMessages();
}
+ private void setUpPrefsForBubbles(boolean globalEnabled, boolean pkgEnabled,
+ boolean channelEnabled) {
+ mService.setPreferencesHelper(mPreferencesHelper);
+ when(mPreferencesHelper.bubblesEnabled(any())).thenReturn(globalEnabled);
+ when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(pkgEnabled);
+ when(mPreferencesHelper.getNotificationChannel(
+ anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
+ mTestNotificationChannel);
+ when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
+ mTestNotificationChannel.getImportance());
+ mTestNotificationChannel.setAllowBubbles(channelEnabled);
+ }
+
private StatusBarNotification generateSbn(String pkg, int uid, long postTime, int userId) {
Notification.Builder nb = new Notification.Builder(mContext, "a")
.setContentTitle("foo")
@@ -4224,13 +4243,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testFlagBubble() throws RemoteException {
// Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
// Notif with bubble metadata but not our other misc requirements
NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
@@ -4252,15 +4265,33 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testFlagBubble_noFlag_appNotAllowed() throws RemoteException {
+ // Bubbles are allowed!
+ setUpPrefsForBubbles(true /* global */, false /* app */, true /* channel */);
+
+ // Notif with bubble metadata but not our other misc requirements
+ NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
+ null /* tvExtender */, true /* isBubble */);
+
+ // Say we're foreground
+ when(mActivityManager.getPackageImportance(nr.sbn.getPackageName())).thenReturn(
+ IMPORTANCE_FOREGROUND);
+
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
+ nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+ waitForIdle();
+
+ StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
+ assertEquals(1, notifs.length);
+ assertEquals((notifs[0].getNotification().flags & FLAG_BUBBLE), 0);
+ assertFalse(mService.getNotificationRecord(
+ nr.sbn.getKey()).getNotification().isBubbleNotification());
+ }
+
+ @Test
public void testFlagBubbleNotifs_flag_appForeground() throws RemoteException {
// Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
// Notif with bubble metadata but not our other misc requirements
NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
@@ -4282,13 +4313,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testFlagBubbleNotifs_noFlag_appNotForeground() throws RemoteException {
// Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
// Notif with bubble metadata but not our other misc requirements
NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
@@ -4310,13 +4335,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testFlagBubbleNotifs_flag_previousForegroundFlag() throws RemoteException {
// Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
// Notif with bubble metadata but not our other misc requirements
NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
@@ -4356,13 +4375,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
public void testFlagBubbleNotifs_noFlag_previousForegroundFlag_afterRemoval()
throws RemoteException {
// Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
// Notif with bubble metadata but not our other misc requirements
NotificationRecord nr1 = generateNotificationRecord(mTestNotificationChannel,
@@ -4410,13 +4423,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testFlagBubbleNotifs_flag_messaging() throws RemoteException {
// Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
// Give it bubble metadata
Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
@@ -4462,13 +4469,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testFlagBubbleNotifs_flag_phonecall() throws RemoteException {
// Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
// Give it bubble metadata
Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
@@ -4503,13 +4504,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testFlagBubbleNotifs_noFlag_phonecall_noForegroundService() throws RemoteException {
// Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
// Give it bubble metadata
Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
@@ -4542,13 +4537,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testFlagBubbleNotifs_noFlag_phonecall_noPerson() throws RemoteException {
// Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
// Give it bubble metadata
Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
@@ -4578,13 +4567,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testFlagBubbleNotifs_noFlag_phonecall_noCategory() throws RemoteException {
// Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
// Give it bubble metadata
Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
@@ -4618,13 +4601,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testFlagBubbleNotifs_noFlag_messaging_appNotAllowed() throws RemoteException {
// Bubbles are NOT allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(false);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
// Give it bubble metadata
Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
@@ -4663,13 +4640,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testFlagBubbleNotifs_noFlag_notBubble() throws RemoteException {
// Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
// Notif WITHOUT bubble metadata
NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
@@ -4686,17 +4657,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testFlagBubbleNotifs_noFlag_messaging_channelNotAllowed() throws RemoteException {
- // Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
-
- // But not on this channel!
- mTestNotificationChannel.setAllowBubbles(false);
+ // Bubbles are allowed except on this channel
+ setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
// Give it bubble metadata
Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
@@ -4734,14 +4696,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testFlagBubbleNotifs_noFlag_phonecall_notAllowed() throws RemoteException {
- // Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(false);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ // Bubbles are not allowed!
+ setUpPrefsForBubbles(false /* global */, true /* app */, true /* channel */);
// Give it bubble metadata
Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
@@ -4775,17 +4731,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testFlagBubbleNotifs_noFlag_phonecall_channelNotAllowed() throws RemoteException {
- // Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(false);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
-
- // But not on this channel!
- mTestNotificationChannel.setAllowBubbles(false);
+ // Bubbles are allowed, but not on channel.
+ setUpPrefsForBubbles(true /* global */, true /* app */, false /* channel */);
// Give it bubble metadata
Notification.BubbleMetadata data = getBasicBubbleMetadataBuilder().build();
@@ -4990,13 +4937,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testNotificationBubbleChanged_false() throws Exception {
// Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
// Notif with bubble metadata but not our other misc requirements
NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
@@ -5034,13 +4975,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testNotificationBubbleChanged_true() throws Exception {
// Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
// Plain notification that has bubble metadata
NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
@@ -5077,13 +5012,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testNotificationBubbleChanged_true_notAllowed() throws Exception {
// Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
// Notif that is not a bubble
NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
@@ -5114,13 +5043,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testNotificationBubbles_disabled_lowRamDevice() throws Exception {
// Bubbles are allowed!
- mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.areBubblesAllowed(anyString(), anyInt())).thenReturn(true);
- when(mPreferencesHelper.getNotificationChannel(
- anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
- mTestNotificationChannel);
- when(mPreferencesHelper.getImportance(anyString(), anyInt())).thenReturn(
- mTestNotificationChannel.getImportance());
+ setUpPrefsForBubbles(true /* global */, true /* app */, true /* channel */);
// Plain notification that has bubble metadata
NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
@@ -5145,6 +5068,5 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
assertEquals(1, notifsAfter.length);
assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
-
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index f8fd64a8feb2..11a177a71a10 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -16,8 +16,6 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_90;
@@ -40,7 +38,6 @@ import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_INVISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -59,10 +56,10 @@ import android.app.servertransaction.PauseActivityItem;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.util.MergedConfiguration;
import android.util.MutableBoolean;
-import android.view.DisplayInfo;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner.Stub;
import android.view.RemoteAnimationAdapter;
@@ -601,67 +598,6 @@ public class ActivityRecordTests extends ActivityTestsBase {
assertNull(mActivity.pendingOptions);
}
- @Test
- public void testSetProcessOverridesConfig() {
- final ActivityRecord defaultDisplayActivity =
- createActivityOnDisplay(true /* defaultDisplay */, null /* process */);
- assertFalse(defaultDisplayActivity.app.registeredForDisplayConfigChanges());
-
- final ActivityRecord secondaryDisplayActivity =
- createActivityOnDisplay(false /* defaultDisplay */, null /* process */);
- assertTrue(secondaryDisplayActivity.app.registeredForDisplayConfigChanges());
- assertEquals(secondaryDisplayActivity.getDisplay().getResolvedOverrideConfiguration(),
- secondaryDisplayActivity.app.getRequestedOverrideConfiguration());
-
- assertNotEquals(defaultDisplayActivity.getConfiguration(),
- secondaryDisplayActivity.getConfiguration());
- }
-
- @Test
- public void testSetProcessDoesntOverrideConfigIfAnotherActivityPresent() {
- final ActivityRecord defaultDisplayActivity =
- createActivityOnDisplay(true /* defaultDisplay */, null /* process */);
- assertFalse(defaultDisplayActivity.app.registeredForDisplayConfigChanges());
-
- final ActivityRecord secondaryDisplayActivity =
- createActivityOnDisplay(false /* defaultDisplay */, defaultDisplayActivity.app);
- assertFalse(secondaryDisplayActivity.app.registeredForDisplayConfigChanges());
- }
-
- @Test
- public void testActivityOnDefaultDisplayClearsProcessOverride() {
- final ActivityRecord secondaryDisplayActivity =
- createActivityOnDisplay(false /* defaultDisplay */, null /* process */);
- assertTrue(secondaryDisplayActivity.app.registeredForDisplayConfigChanges());
-
- final ActivityRecord defaultDisplayActivity =
- createActivityOnDisplay(true /* defaultDisplay */,
- secondaryDisplayActivity.app);
- assertFalse(defaultDisplayActivity.app.registeredForDisplayConfigChanges());
- assertFalse(secondaryDisplayActivity.app.registeredForDisplayConfigChanges());
- }
-
- /**
- * Creates an activity on display. For non-default display request it will also create a new
- * display with custom DisplayInfo.
- */
- private ActivityRecord createActivityOnDisplay(boolean defaultDisplay,
- WindowProcessController process) {
- final ActivityDisplay display;
- if (defaultDisplay) {
- display = mRootActivityContainer.getDefaultDisplay();
- } else {
- final DisplayInfo info = new DisplayInfo();
- info.logicalWidth = 100;
- info.logicalHeight = 100;
- display = addNewActivityDisplayAt(info, POSITION_TOP);
- }
- final TestActivityStack stack = display.createStack(WINDOWING_MODE_UNDEFINED,
- ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build();
- return new ActivityBuilder(mService).setTask(task).setUseProcess(process).build();
- }
-
/** Setup {@link #mActivity} as a size-compat-mode-able activity without fixed orientation. */
private void prepareFixedAspectRatioUnresizableActivity() {
setupDisplayContentForCompatDisplayInsets();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index d8c0de741845..53b0add8c37e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -195,7 +195,6 @@ class ActivityTestsBase {
private ActivityStack mStack;
private int mActivityFlags;
private int mLaunchMode;
- private WindowProcessController mWpc;
ActivityBuilder(ActivityTaskManagerService service) {
mService = service;
@@ -246,11 +245,6 @@ class ActivityTestsBase {
return this;
}
- ActivityBuilder setUseProcess(WindowProcessController wpc) {
- mWpc = wpc;
- return this;
- }
-
ActivityRecord build() {
if (mComponent == null) {
final int id = sCurrentActivityId++;
@@ -296,18 +290,12 @@ class ActivityTestsBase {
mTaskRecord.addActivityToTop(activity);
}
- final WindowProcessController wpc;
- if (mWpc != null) {
- wpc = mWpc;
- } else {
- wpc = new WindowProcessController(mService,
- mService.mContext.getApplicationInfo(), "name", 12345,
- UserHandle.getUserId(12345), mock(Object.class),
- mock(WindowProcessListener.class));
- wpc.setThread(mock(IApplicationThread.class));
- }
+ final WindowProcessController wpc = new WindowProcessController(mService,
+ mService.mContext.getApplicationInfo(), "name", 12345,
+ UserHandle.getUserId(12345), mock(Object.class),
+ mock(WindowProcessListener.class));
+ wpc.setThread(mock(IApplicationThread.class));
activity.setProcess(wpc);
- wpc.addActivityIfNeeded(activity);
return activity;
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 8528954a6b5b..7f35dac9611a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -153,6 +153,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
@FlakyTest(bugId = 131005232)
public void testLandscapeSeascapeRotationByApp() {
// Some plumbing to get the service ready for rotation updates.
+ mWm.mDisplayReady = true;
mWm.mDisplayEnabled = true;
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
@@ -185,6 +186,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
@Test
public void testLandscapeSeascapeRotationByPolicy() {
// Some plumbing to get the service ready for rotation updates.
+ mWm.mDisplayReady = true;
mWm.mDisplayEnabled = true;
final DisplayRotation spiedRotation = spy(mDisplayContent.getDisplayRotation());
diff --git a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
new file mode 100644
index 000000000000..558672609304
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+
+import com.android.server.wm.HighRefreshRateBlacklist.SystemPropertyGetter;
+
+import org.junit.Test;
+
+/**
+ * Build/Install/Run:
+ * atest WmTests:HighRefreshRateBlacklistTest
+ */
+@SmallTest
+@Presubmit
+@FlakyTest
+public class HighRefreshRateBlacklistTest {
+
+ @Test
+ public void testBlacklist() {
+ HighRefreshRateBlacklist blacklist = new HighRefreshRateBlacklist(
+ new SystemPropertyGetter() {
+
+ @Override
+ public int getInt(String key, int def) {
+ if ("ro.window_manager.high_refresh_rate_blacklist_length".equals(key)) {
+ return 2;
+ }
+ return def;
+ }
+
+ @Override
+ public String get(String key) {
+ if ("ro.window_manager.high_refresh_rate_blacklist_entry1".equals(key)) {
+ return "com.android.sample1";
+ }
+ if ("ro.window_manager.high_refresh_rate_blacklist_entry2".equals(key)) {
+ return "com.android.sample2";
+ }
+ return "";
+ }
+ });
+ assertTrue(blacklist.isBlacklisted("com.android.sample1"));
+ assertTrue(blacklist.isBlacklisted("com.android.sample2"));
+ assertFalse(blacklist.isBlacklisted("com.android.sample3"));
+ }
+
+ @Test
+ public void testNoBlacklist() {
+ HighRefreshRateBlacklist blacklist = new HighRefreshRateBlacklist(
+ new SystemPropertyGetter() {
+
+ @Override
+ public int getInt(String key, int def) {
+ return def;
+ }
+
+ @Override
+ public String get(String key) {
+ return "";
+ }
+ });
+ assertFalse(blacklist.isBlacklisted("com.android.sample1"));
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
new file mode 100644
index 000000000000..efc2fd60ba37
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.platform.test.annotations.Presubmit;
+import android.view.Display.Mode;
+import android.view.DisplayInfo;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Build/Install/Run:
+ * atest WmTests:RefreshRatePolicyTest
+ */
+@SmallTest
+@Presubmit
+@FlakyTest
+public class RefreshRatePolicyTest extends WindowTestsBase {
+
+ private static final int LOW_MODE_ID = 3;
+
+ private RefreshRatePolicy mPolicy;
+ private HighRefreshRateBlacklist mBlacklist = mock(HighRefreshRateBlacklist.class);
+
+ @Before
+ public void setUp() {
+ DisplayInfo di = new DisplayInfo(mDisplayInfo);
+ Mode defaultMode = di.getDefaultMode();
+ di.supportedModes = new Mode[] {
+ new Mode(1, defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), 90),
+ new Mode(2, defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), 70),
+ new Mode(LOW_MODE_ID,
+ defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), 60),
+ };
+ di.defaultModeId = 1;
+ mPolicy = new RefreshRatePolicy(mWm, di, mBlacklist);
+ }
+
+ @Test
+ public void testCamera() {
+ final WindowState cameraUsingWindow = createWindow(null, TYPE_BASE_APPLICATION,
+ "cameraUsingWindow");
+ cameraUsingWindow.mAttrs.packageName = "com.android.test";
+ assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
+ mPolicy.addNonHighRefreshRatePackage("com.android.test");
+ assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(cameraUsingWindow));
+ mPolicy.removeNonHighRefreshRatePackage("com.android.test");
+ assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
+ }
+
+ @Test
+ public void testBlacklist() {
+ final WindowState blacklistedWindow = createWindow(null, TYPE_BASE_APPLICATION,
+ "blacklistedWindow");
+ blacklistedWindow.mAttrs.packageName = "com.android.test";
+ when(mBlacklist.isBlacklisted("com.android.test")).thenReturn(true);
+ assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(blacklistedWindow));
+ }
+
+ @Test
+ public void testAppOverride_blacklist() {
+ final WindowState overrideWindow = createWindow(null, TYPE_BASE_APPLICATION,
+ "overrideWindow");
+ overrideWindow.mAttrs.preferredDisplayModeId = LOW_MODE_ID;
+ when(mBlacklist.isBlacklisted("com.android.test")).thenReturn(true);
+ assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(overrideWindow));
+ }
+
+ @Test
+ public void testAppOverride_camera() {
+ final WindowState overrideWindow = createWindow(null, TYPE_BASE_APPLICATION,
+ "overrideWindow");
+ overrideWindow.mAttrs.packageName = "com.android.test";
+ overrideWindow.mAttrs.preferredDisplayModeId = LOW_MODE_ID;
+ mPolicy.addNonHighRefreshRatePackage("com.android.test");
+ assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(overrideWindow));
+ }
+
+ @Test
+ public void testAnimatingAppOverride() {
+ final WindowState overrideWindow = createWindow(null, TYPE_BASE_APPLICATION,
+ "overrideWindow");
+ overrideWindow.mAttrs.packageName = "com.android.test";
+ overrideWindow.mAttrs.preferredDisplayModeId = LOW_MODE_ID;
+ overrideWindow.mAppToken.mSurfaceAnimator.startAnimation(
+ overrideWindow.getPendingTransaction(), mock(AnimationAdapter.class),
+ false /* hidden */);
+ mPolicy.addNonHighRefreshRatePackage("com.android.test");
+ assertEquals(0, mPolicy.getPreferredModeId(overrideWindow));
+ }
+
+ @Test
+ public void testAnimatingCamera() {
+ final WindowState cameraUsingWindow = createWindow(null, TYPE_BASE_APPLICATION,
+ "cameraUsingWindow");
+ cameraUsingWindow.mAttrs.packageName = "com.android.test";
+
+ mPolicy.addNonHighRefreshRatePackage("com.android.test");
+ assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(cameraUsingWindow));
+
+ cameraUsingWindow.mAppToken.mSurfaceAnimator.startAnimation(
+ cameraUsingWindow.getPendingTransaction(), mock(AnimationAdapter.class),
+ false /* hidden */);
+ assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 427a92963807..366aceafd7bf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -41,7 +41,6 @@ import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IntentFilter;
-import android.content.res.Configuration;
import android.database.ContentObserver;
import android.hardware.display.DisplayManagerInternal;
import android.net.Uri;
@@ -176,12 +175,6 @@ public class SystemServicesTestRule implements TestRule {
// Display creation is driven by the ActivityManagerService via
// ActivityStackSupervisor. We emulate those steps here.
mWindowManagerService.mRoot.createDisplayContent(display, mock(ActivityDisplay.class));
- mWindowManagerService.displayReady();
-
- final Configuration defaultDisplayConfig =
- mWindowManagerService.computeNewConfiguration(DEFAULT_DISPLAY);
- doReturn(defaultDisplayConfig).when(atms).getGlobalConfiguration();
- doReturn(defaultDisplayConfig).when(atms).getGlobalConfigurationForPid(anyInt());
mMockTracker.stopTracking();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index 7b8fba03b6d7..a7c84a1c28b4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -26,9 +26,7 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import android.content.pm.ApplicationInfo;
-import android.content.res.Configuration;
import android.platform.test.annotations.Presubmit;
-import android.view.DisplayInfo;
import org.junit.Test;
@@ -80,26 +78,6 @@ public class WindowProcessControllerTests extends ActivityTestsBase {
assertEquals(INVALID_DISPLAY, wpc.getDisplayId());
}
- @Test
- public void testConfigurationForSecondaryScreen() {
- final WindowProcessController wpc = new WindowProcessController(
- mService, mock(ApplicationInfo.class), null, 0, -1, null, null);
- //By default, the process should not listen to any display.
- assertEquals(INVALID_DISPLAY, wpc.getDisplayId());
-
- // Register to a new display as a listener.
- final DisplayInfo info = new DisplayInfo();
- info.logicalWidth = 100;
- info.logicalHeight = 100;
- TestActivityDisplay display = addNewActivityDisplayAt(info, WindowContainer.POSITION_TOP);
- wpc.registerDisplayConfigurationListenerLocked(display);
-
- assertEquals(display.mDisplayId, wpc.getDisplayId());
- final Configuration expectedConfig = mService.mRootActivityContainer.getConfiguration();
- expectedConfig.updateFrom(display.getConfiguration());
- assertEquals(expectedConfig, wpc.getConfiguration());
- }
-
private TestActivityDisplay createTestActivityDisplayInContainer() {
final TestActivityDisplay testActivityDisplay = createNewActivityDisplay();
mRootActivityContainer.addChild(testActivityDisplay, POSITION_TOP);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index de28b5f0fa4f..3a702cb9521c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -154,6 +154,7 @@ class WindowTestsBase {
context.getDisplay().getDisplayInfo(mDisplayInfo);
mDisplayContent = createNewDisplay();
mWm.mDisplayEnabled = true;
+ mWm.mDisplayReady = true;
// Set-up some common windows.
mCommonWindows = new HashSet<>();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 2a5b70bf77f2..a1210cfce26d 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -29,7 +29,6 @@ import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.IActivityManager;
import android.app.IActivityTaskManager;
-import android.app.IApplicationThread;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -48,7 +47,6 @@ import android.service.voice.IVoiceInteractionService;
import android.service.voice.IVoiceInteractionSession;
import android.service.voice.VoiceInteractionService;
import android.service.voice.VoiceInteractionServiceInfo;
-import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.view.IWindowManager;
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 49b34b38c663..c66e92b5e099 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -1937,6 +1937,8 @@ public abstract class ConnectionService extends Service {
return;
}
+ String callingPackage = getOpPackageName();
+
mAdapter.queryRemoteConnectionServices(new RemoteServiceCallback.Stub() {
@Override
public void onResult(
@@ -1965,7 +1967,7 @@ public abstract class ConnectionService extends Service {
}
}.prepare());
}
- });
+ }, callingPackage);
}
/**
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index 6c3f4f34ff2d..3acd83a41396 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -316,11 +316,11 @@ final class ConnectionServiceAdapter implements DeathRecipient {
/**
* Retrieves a list of remote connection services usable to place calls.
*/
- void queryRemoteConnectionServices(RemoteServiceCallback callback) {
+ void queryRemoteConnectionServices(RemoteServiceCallback callback, String callingPackage) {
// Only supported when there is only one adapter.
if (mAdapters.size() == 1) {
try {
- mAdapters.iterator().next().queryRemoteConnectionServices(callback,
+ mAdapters.iterator().next().queryRemoteConnectionServices(callback, callingPackage,
Log.getExternalSession());
} catch (RemoteException e) {
Log.e(this, e, "Exception trying to query for remote CSs");
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index f99b218bd9b9..b28158913dc4 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -186,8 +186,13 @@ final class ConnectionServiceAdapterServant {
break;
}
case MSG_QUERY_REMOTE_CALL_SERVICES:
- mDelegate.queryRemoteConnectionServices((RemoteServiceCallback) msg.obj,
- null /*Session.Info*/);
+ SomeArgs args2 = (SomeArgs) msg.obj;
+ try {
+ mDelegate.queryRemoteConnectionServices((RemoteServiceCallback) args2.arg1,
+ (String) args2.arg2, null /*Session.Info*/);
+ } finally {
+ args2.recycle();
+ }
break;
case MSG_SET_VIDEO_STATE:
mDelegate.setVideoState((String) msg.obj, msg.arg1, null /*Session.Info*/);
@@ -468,7 +473,10 @@ final class ConnectionServiceAdapterServant {
@Override
public void queryRemoteConnectionServices(RemoteServiceCallback callback,
- Session.Info sessionInfo) {
+ String callingPackage, Session.Info sessionInfo) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = callback;
+ args.arg2 = callingPackage;
mHandler.obtainMessage(MSG_QUERY_REMOTE_CALL_SERVICES, callback).sendToTarget();
}
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index 744544eb01f1..1e73bd61d68e 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -288,7 +288,7 @@ final class RemoteConnectionService {
@Override
public void queryRemoteConnectionServices(RemoteServiceCallback callback,
- Session.Info sessionInfo) {
+ String callingPackage, Session.Info sessionInfo) {
// Not supported from remote connection service.
}
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index 76ac88e9fbaa..9cf098c75177 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -78,7 +78,8 @@ oneway interface IConnectionServiceAdapter {
void onPostDialChar(String callId, char nextChar, in Session.Info sessionInfo);
- void queryRemoteConnectionServices(RemoteServiceCallback callback, in Session.Info sessionInfo);
+ void queryRemoteConnectionServices(RemoteServiceCallback callback, String callingPackage,
+ in Session.Info sessionInfo);
void setVideoProvider(String callId, IVideoProvider videoProvider, in Session.Info sessionInfo);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 6ba359b78ee4..5175c1daf3c0 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2794,14 +2794,6 @@ public class CarrierConfigManager {
*/
public static final String KEY_NFW_PROXY_APPS_STRING = KEY_PREFIX + "nfw_proxy_apps";
- /**
- * Specify whether to post a notification on the status bar whenever device location is
- * provided for non-framework location requests in user-initiated emergency use cases.
- * 0 - Do not post notification. This is default.
- * 1 - Post notification for all request types.
- */
- public static final String KEY_ES_NOTIFY_INT = KEY_PREFIX + "es_notify_int";
-
private static PersistableBundle getDefaults() {
PersistableBundle defaults = new PersistableBundle();
defaults.putBoolean(KEY_PERSIST_LPP_MODE_BOOL, true);
@@ -2816,7 +2808,6 @@ public class CarrierConfigManager {
defaults.putString(KEY_GPS_LOCK_STRING, "3");
defaults.putString(KEY_ES_EXTENSION_SEC_STRING, "0");
defaults.putString(KEY_NFW_PROXY_APPS_STRING, "");
- defaults.putInt(KEY_ES_NOTIFY_INT, 0);
return defaults;
}
}
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index f31ac2ea5f35..1e6cd474d13b 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -735,7 +735,7 @@ public class SubscriptionInfo implements Parcelable {
return "{id=" + mId + ", iccId=" + iccIdToPrint + " simSlotIndex=" + mSimSlotIndex
+ " carrierId=" + mCarrierId + " displayName=" + mDisplayName
+ " carrierName=" + mCarrierName + " nameSource=" + mNameSource
- + " iconTint=" + mIconTint + " mNumber=" + mNumber
+ + " iconTint=" + mIconTint + " mNumber=" + Rlog.pii(Build.IS_DEBUGGABLE, mNumber)
+ " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc " + mMcc
+ " mnc " + mMnc + "mCountryIso=" + mCountryIso + " isEmbedded " + mIsEmbedded
+ " accessRules " + Arrays.toString(mAccessRules)
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index dab1e6f4abde..4a58d949ea82 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2246,7 +2246,7 @@ public class TelephonyManager {
@UnsupportedAppUsage
public String getNetworkOperatorForPhone(int phoneId) {
return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, "");
- }
+ }
/**
@@ -2446,21 +2446,7 @@ public class TelephonyManager {
* @return the NETWORK_TYPE_xxxx for current data connection.
*/
public @NetworkType int getNetworkType() {
- try {
- ITelephony telephony = getITelephony();
- if (telephony != null) {
- return telephony.getNetworkType();
- } else {
- // This can happen when the ITelephony interface is not up yet.
- return NETWORK_TYPE_UNKNOWN;
- }
- } catch(RemoteException ex) {
- // This shouldn't happen in the normal case
- return NETWORK_TYPE_UNKNOWN;
- } catch (NullPointerException ex) {
- // This could happen before phone restarts due to crashing
- return NETWORK_TYPE_UNKNOWN;
- }
+ return getNetworkType(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
}
/**
@@ -2491,7 +2477,7 @@ public class TelephonyManager {
* @hide
*/
@RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public int getNetworkType(int subId) {
try {
ITelephony telephony = getITelephony();
diff --git a/telephony/java/android/telephony/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java
index 18e7530a790e..9912eced0543 100644
--- a/telephony/java/android/telephony/ims/ImsSsInfo.java
+++ b/telephony/java/android/telephony/ims/ImsSsInfo.java
@@ -250,6 +250,8 @@ public final class ImsSsInfo implements Parcelable {
out.writeInt(mStatus);
out.writeString(mIcbNum);
out.writeInt(mProvisionStatus);
+ out.writeInt(mClirInterrogationStatus);
+ out.writeInt(mClirOutgoingState);
}
@Override
@@ -273,6 +275,8 @@ public final class ImsSsInfo implements Parcelable {
mStatus = in.readInt();
mIcbNum = in.readString();
mProvisionStatus = in.readInt();
+ mClirInterrogationStatus = in.readInt();
+ mClirOutgoingState = in.readInt();
}
public static final @android.annotation.NonNull Creator<ImsSsInfo> CREATOR =
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 68fd9ac8d6bd..63aded1c4b20 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -460,13 +460,6 @@ interface ITelephony {
void sendDialerSpecialCode(String callingPackageName, String inputCode);
/**
- * Returns the network type for data transmission
- * Legacy call, permission-free
- */
- @UnsupportedAppUsage
- int getNetworkType();
-
- /**
* Returns the network type of a subId.
* @param subId user preferred subId.
* @param callingPackage package making the call.
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index 2552f045eedf..e8e2a3d8453e 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -102,6 +102,16 @@ public final class TelephonyPermissions {
callingPackage, message);
}
+ /** Identical to checkCallingOrSelfReadPhoneState but never throws SecurityException */
+ public static boolean checkCallingOrSelfReadPhoneStateNoThrow(
+ Context context, int subId, String callingPackage, String message) {
+ try {
+ return checkCallingOrSelfReadPhoneState(context, subId, callingPackage, message);
+ } catch (SecurityException se) {
+ return false;
+ }
+ }
+
/**
* Check whether the app with the given pid/uid can read phone state.
*
diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp
index 1932871d86b9..1cf3d364a8d5 100644
--- a/tests/RollbackTest/Android.bp
+++ b/tests/RollbackTest/Android.bp
@@ -78,45 +78,6 @@ android_test_helper_app {
package_splits: ["anydpi"],
}
-apex {
- name: "com.android.tests.rollback.testapex.RollbackTestApexV1",
- manifest: "TestApex/RollbackTestApexV1.json",
- file_contexts: "apex.test",
- prebuilts: ["RollbackTestApex.prebuilt.txt"],
- key: "RollbackTestApex.key",
- installable: false,
-}
-
-apex {
- name: "com.android.tests.rollback.testapex.RollbackTestApexV2",
- manifest: "TestApex/RollbackTestApexV2.json",
- file_contexts: "apex.test",
- prebuilts: ["RollbackTestApex.prebuilt.txt"],
- key: "RollbackTestApex.key",
- installable: false,
-}
-
-apex {
- name: "com.android.tests.rollback.testapex.RollbackTestApexV3",
- manifest: "TestApex/RollbackTestApexV3.json",
- file_contexts: "apex.test",
- prebuilts: ["RollbackTestApex.prebuilt.txt"],
- key: "RollbackTestApex.key",
- installable: false,
-}
-
-apex_key {
- name: "RollbackTestApex.key",
- public_key: "TestApex/com.android.tests.rollback.testapex.avbpubkey",
- private_key: "TestApex/com.android.tests.rollback.testapex.pem",
- installable: false,
-}
-
-prebuilt_etc {
- name: "RollbackTestApex.prebuilt.txt",
- src: "TestApex/RollbackTestApex.prebuilt.txt",
-}
-
android_test {
name: "RollbackTest",
manifest: "RollbackTest/AndroidManifest.xml",
@@ -132,9 +93,6 @@ android_test {
":RollbackTestAppBv2",
":RollbackTestAppASplitV1",
":RollbackTestAppASplitV2",
- ":com.android.tests.rollback.testapex.RollbackTestApexV1",
- ":com.android.tests.rollback.testapex.RollbackTestApexV2",
- ":com.android.tests.rollback.testapex.RollbackTestApexV3",
],
test_config: "RollbackTest.xml",
sdk_version: "test_current",
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index b3a9f4933de9..1ddfa6ee54ce 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -17,7 +17,6 @@
package com.android.tests.rollback;
import static com.android.tests.rollback.RollbackTestUtils.assertRollbackInfoEquals;
-import static com.android.tests.rollback.RollbackTestUtils.getRecentlyCommittedRollbackInfoById;
import static com.android.tests.rollback.RollbackTestUtils.getUniqueRollbackInfoForPackage;
import android.Manifest;
@@ -31,7 +30,6 @@ import androidx.test.InstrumentationRegistry;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -55,15 +53,7 @@ public class StagedRollbackTest {
private static final String TAG = "RollbackTest";
private static final String TEST_APP_A = "com.android.tests.rollback.testapp.A";
private static final String TEST_APP_A_V1 = "RollbackTestAppAv1.apk";
- private static final String TEST_APP_A_V2 = "RollbackTestAppAv2.apk";
private static final String TEST_APP_A_CRASHING_V2 = "RollbackTestAppACrashingV2.apk";
- private static final String TEST_APEX_PKG = "com.android.tests.rollback.testapex";
- private static final String TEST_APEX_V1 =
- "com.android.tests.rollback.testapex.RollbackTestApexV1.apex";
- private static final String TEST_APEX_V2 =
- "com.android.tests.rollback.testapex.RollbackTestApexV2.apex";
- private static final String TEST_APEX_V3 =
- "com.android.tests.rollback.testapex.RollbackTestApexV3.apex";
/**
* Adopts common shell permissions needed for rollback tests.
@@ -85,59 +75,6 @@ public class StagedRollbackTest {
RollbackTestUtils.dropShellPermissionIdentity();
}
-
- /**
- * Test rollbacks of staged installs involving only apks.
- * Enable rollback phase.
- */
- @Test
- public void testApkOnlyEnableRollback() throws Exception {
- RollbackTestUtils.uninstall(TEST_APP_A);
- assertEquals(-1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
- RollbackTestUtils.install(TEST_APP_A_V1, false);
- assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
- RollbackTestUtils.processUserData(TEST_APP_A);
-
- RollbackTestUtils.installStaged(true, TEST_APP_A_V2);
-
- // At this point, the host test driver will reboot the device and run
- // testApkOnlyCommitRollback().
- }
-
- /**
- * Test rollbacks of staged installs involving only apks.
- * Commit rollback phase.
- */
- @Test
- public void testApkOnlyCommitRollback() throws Exception {
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
- RollbackTestUtils.processUserData(TEST_APP_A);
-
- RollbackManager rm = RollbackTestUtils.getRollbackManager();
- RollbackInfo rollback = getUniqueRollbackInfoForPackage(
- rm.getAvailableRollbacks(), TEST_APP_A);
- assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback);
- assertTrue(rollback.isStaged());
-
- RollbackTestUtils.rollback(rollback.getRollbackId(),
- new VersionedPackage(TEST_APP_A, 2));
-
- rollback = getUniqueRollbackInfoForPackage(
- rm.getRecentlyCommittedRollbacks(), TEST_APP_A);
- assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback, new VersionedPackage(TEST_APP_A, 2));
- assertTrue(rollback.isStaged());
- assertNotEquals(-1, rollback.getCommittedSessionId());
-
- RollbackTestUtils.waitForSessionReady(rollback.getCommittedSessionId());
-
- // The app should not be rolled back until after reboot.
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
- // At this point, the host test driver will reboot the device and run
- // testApkOnlyConfirmRollback().
- }
-
/**
* Test rollbacks of staged installs involving only apks with bad update.
* Enable rollback phase.
@@ -209,7 +146,7 @@ public class StagedRollbackTest {
* Confirm rollback phase.
*/
@Test
- public void testApkOnlyConfirmRollback() throws Exception {
+ public void testBadApkOnlyConfirmRollback() throws Exception {
assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
RollbackTestUtils.processUserData(TEST_APP_A);
@@ -220,171 +157,4 @@ public class StagedRollbackTest {
assertTrue(rollback.isStaged());
assertNotEquals(-1, rollback.getCommittedSessionId());
}
-
- /**
- * Test rollbacks of staged installs an apk and an apex.
- * Enable rollback phase.
- */
- @Test
- public void testApkAndApexEnableRollback() throws Exception {
- RollbackTestUtils.uninstall(TEST_APP_A);
- RollbackTestUtils.install(TEST_APP_A_V1, false);
-
- assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
- assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
- RollbackTestUtils.installStaged(true, TEST_APP_A_V2, TEST_APEX_V2);
-
- // At this point, the host test driver will reboot the device and run
- // testApkAndApexCommitRollback().
- }
-
- /**
- * Test rollbacks of staged installs an apk and an apex.
- * Commit rollback phase.
- */
- @Test
- public void testApkAndApexCommitRollback() throws Exception {
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
- RollbackTestUtils.processUserData(TEST_APP_A);
-
- RollbackManager rm = RollbackTestUtils.getRollbackManager();
-
- RollbackInfo rollback = getUniqueRollbackInfoForPackage(
- rm.getAvailableRollbacks(), TEST_APP_A);
- String[] packagesNames = {TEST_APEX_PKG, TEST_APP_A};
- assertRollbackInfoEquals(packagesNames, 2, 1, rollback);
- assertTrue(rollback.isStaged());
-
- RollbackTestUtils.rollback(rollback.getRollbackId());
-
- RollbackInfo committed = getRecentlyCommittedRollbackInfoById(rollback.getRollbackId());
-
- assertRollbackInfoEquals(packagesNames, 2, 1, committed);
- assertTrue(committed.isStaged());
- assertNotEquals(-1, committed.getCommittedSessionId());
-
- RollbackTestUtils.waitForSessionReady(committed.getCommittedSessionId());
-
- // The apex and apk should not be rolled back until after reboot.
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
- // At this point, the host test driver will reboot the device and run
- // testApkAndApexConfirmRollback().
- }
-
- /**
- * Test rollbacks of staged installs an apk and an apex.
- * Confirm rollback phase.
- */
- @Test
- public void testApkAndApexConfirmRollback() throws Exception {
- assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
- assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
-
- RollbackTestUtils.processUserData(TEST_APP_A);
- }
-
- /**
- * Test rollbacks of staged installs involving only apex.
- * Enable rollback phase.
- */
- @Test
- public void testApexOnlyEnableRollback() throws Exception {
- assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
- RollbackTestUtils.installStaged(true, TEST_APEX_V2);
-
- // At this point, the host test driver will reboot the device and run
- // testApexOnlyCommitRollback().
- }
-
- /**
- * Test rollbacks of staged installs involving only apex.
- * Commit rollback phase.
- */
- @Test
- public void testApexOnlyCommitRollback() throws Exception {
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-
- RollbackManager rm = RollbackTestUtils.getRollbackManager();
- RollbackInfo rollback = getUniqueRollbackInfoForPackage(
- rm.getAvailableRollbacks(), TEST_APEX_PKG);
- assertRollbackInfoEquals(TEST_APEX_PKG, 2, 1, rollback);
- assertTrue(rollback.isStaged());
-
- RollbackTestUtils.rollback(rollback.getRollbackId());
-
- RollbackInfo committed = getRecentlyCommittedRollbackInfoById(rollback.getRollbackId());
-
- assertRollbackInfoEquals(TEST_APEX_PKG, 2, 1, committed);
- assertTrue(committed.isStaged());
- assertNotEquals(-1, committed.getCommittedSessionId());
-
- RollbackTestUtils.waitForSessionReady(committed.getCommittedSessionId());
-
- // The apex should not be rolled back until after reboot.
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-
- // At this point, the host test driver will reboot the device and run
- // testApexOnlyConfirmRollback().
- }
-
- /**
- * Test rollbacks of staged installs involving only apex.
- * Confirm rollback phase.
- */
- @Test
- public void testApexOnlyConfirmRollback() throws Exception {
- assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
- }
-
- /**
- * Tests that apex update expires existing rollbacks for that apex.
- * Enable rollback phase.
- */
- @Test
- public void testApexRollbackExpirationEnableRollback() throws Exception {
- assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
- RollbackTestUtils.installStaged(true, TEST_APEX_V2);
-
- // At this point, the host test driver will reboot the device and run
- // testApexRollbackExpirationUpdateApex().
- }
-
- /**
- * Tests that apex update expires existing rollbacks for that apex.
- * Update apex phase.
- */
- @Test
- public void testApexRollbackExpirationUpdateApex() throws Exception {
- assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
- RollbackTestUtils.installStaged(false, TEST_APEX_V3);
-
- // At this point, the host test driver will reboot the device and run
- // testApexRollbackExpirationConfirmExpiration().
- }
-
- /**
- * Tests that apex update expires existing rollbacks for that apex.
- * Confirm expiration phase.
- */
- @Test
- public void testApexRollbackExpirationConfirmExpiration() throws Exception {
- assertEquals(3, RollbackTestUtils.getInstalledVersion(TEST_APEX_PKG));
-
- RollbackManager rm = RollbackTestUtils.getRollbackManager();
- assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APEX_PKG));
- }
-
- /**
- * Helper function called by the host test to install v1 of the test apex,
- * assuming the test apex is not installed.
- */
- @Test
- public void installTestApexV1() throws Exception {
- RollbackTestUtils.installStaged(false, TEST_APEX_V1);
- }
}
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 2433434a2993..75a95adf460a 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -19,7 +19,6 @@ package com.android.tests.rollback.host;
import static org.junit.Assert.assertTrue;
import com.android.ddmlib.Log.LogLevel;
-import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -32,9 +31,6 @@ import org.junit.runner.RunWith;
*/
@RunWith(DeviceJUnit4ClassRunner.class)
public class StagedRollbackTest extends BaseHostJUnit4Test {
-
- private static final String TEST_APEX_PKG = "com.android.tests.rollback.testapex";
-
/**
* Runs the given phase of a test by calling into the device.
* Throws an exception if the test phase fails.
@@ -48,18 +44,6 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
}
/**
- * Tests staged rollbacks involving only apks.
- */
- @Test
- public void testApkOnly() throws Exception {
- runPhase("testApkOnlyEnableRollback");
- getDevice().reboot();
- runPhase("testApkOnlyCommitRollback");
- getDevice().reboot();
- runPhase("testApkOnlyConfirmRollback");
- }
-
- /**
* Tests watchdog triggered staged rollbacks involving only apks.
*/
@Test
@@ -79,66 +63,6 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
}
getDevice().waitForDeviceAvailable();
- runPhase("testApkOnlyConfirmRollback");
- }
-
- /**
- * Tests staged rollbacks involving only apex.
- */
- @Test
- public void testApexOnly() throws Exception {
- installTestApexV1();
- runPhase("testApexOnlyEnableRollback");
- getDevice().reboot();
- runPhase("testApexOnlyCommitRollback");
- getDevice().reboot();
- runPhase("testApexOnlyConfirmRollback");
- }
-
- /**
- * Tests staged rollbacks involving apk and apex.
- */
- @Test
- public void testApkAndApex() throws Exception {
- installTestApexV1();
- runPhase("testApkAndApexEnableRollback");
- getDevice().reboot();
- runPhase("testApkAndApexCommitRollback");
- getDevice().reboot();
- runPhase("testApkAndApexConfirmRollback");
- }
-
- /**
- * Tests that apex update expires existing rollbacks for that apex.
- */
- @Test
- public void testApexRollbackExpiration() throws Exception {
- installTestApexV1();
- runPhase("testApexRollbackExpirationEnableRollback");
- getDevice().reboot();
- runPhase("testApexRollbackExpirationUpdateApex");
- getDevice().reboot();
- runPhase("testApexRollbackExpirationConfirmExpiration");
- }
-
- /**
- * Do whatever is necessary to get version 1 of the test apex installed on
- * the device. Try to do so without extra reboots where possible to keep
- * the test execution time down.
- */
- private void installTestApexV1() throws Exception {
- for (ITestDevice.ApexInfo apexInfo : getDevice().getActiveApexes()) {
- if (TEST_APEX_PKG.equals(apexInfo.name)) {
- if (apexInfo.versionCode == 1) {
- return;
- }
- getDevice().uninstallPackage(TEST_APEX_PKG);
- getDevice().reboot();
- break;
- }
- }
-
- runPhase("installTestApexV1");
- getDevice().reboot();
+ runPhase("testBadApkOnlyConfirmRollback");
}
}
diff --git a/tests/RollbackTest/TestApex/RollbackTestApex.prebuilt.txt b/tests/RollbackTest/TestApex/RollbackTestApex.prebuilt.txt
deleted file mode 100644
index e871146fb824..000000000000
--- a/tests/RollbackTest/TestApex/RollbackTestApex.prebuilt.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-This file contains dummy content to include in the RollbackTestApex.
-
diff --git a/tests/RollbackTest/TestApex/RollbackTestApexV1.json b/tests/RollbackTest/TestApex/RollbackTestApexV1.json
deleted file mode 100644
index c3239ca0d902..000000000000
--- a/tests/RollbackTest/TestApex/RollbackTestApexV1.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.tests.rollback.testapex",
- "version": 1
-}
diff --git a/tests/RollbackTest/TestApex/RollbackTestApexV2.json b/tests/RollbackTest/TestApex/RollbackTestApexV2.json
deleted file mode 100644
index 9de3f4590877..000000000000
--- a/tests/RollbackTest/TestApex/RollbackTestApexV2.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.tests.rollback.testapex",
- "version": 2
-}
diff --git a/tests/RollbackTest/TestApex/RollbackTestApexV3.json b/tests/RollbackTest/TestApex/RollbackTestApexV3.json
deleted file mode 100644
index 87a2c9dbcb6a..000000000000
--- a/tests/RollbackTest/TestApex/RollbackTestApexV3.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.tests.rollback.testapex",
- "version": 3
-}
diff --git a/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.avbpubkey b/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.avbpubkey
deleted file mode 100644
index b347331bc539..000000000000
--- a/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.pem b/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.pem
deleted file mode 100644
index 7181ce5c2a73..000000000000
--- a/tests/RollbackTest/TestApex/com.android.tests.rollback.testapex.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKQIBAAKCAgEArBLX+v6RMiK6soQFgbc0RZ+wticTD5sCbu9Q5B5WT7UnV1Wt
-cNI/n2bjks3UYNxTneOzMQOVjd4ln0BYZoNvoDtrc1BsYABpt4FywSq1zz/3sp3L
-3Vp8vaUyRsx0Da+PcOdYHPFs1WPX3Shw3MSPhUO/72KTm6GhO/cHEPEzSQLaw/zO
-8FiPpDdRqILqVJlu1DZ+i1DO+To9mKt59uLlxy3F+HAMnQaNW6+2NCV/vdCxQrEL
-m7PpsM6DymsFKcvVra1Il4apKkYNgcgTQ+AlmyPxGo6twfZvRMrU3bcrUmrg3OAx
-tMD7MufXlKkoFMlT5clrQ7P2ErKoFxhTVWhBL5ZJv/lKwaTfxCLyNvYQ7JALKtOL
-9xx4c77NdyYVjxMDAJ7E+Uj3QjdOv3FxM38Fcvt0zN4SSlmDjEDtm2e2w53Ztgz1
-zHAuNllIW1zGdPqa+ROoa9JLJePlyNXG9Rn1sSkjM9WwteaJ3nrdje6uBsvo7I9g
-1MWab2XNXQwJNHACICtyU7QPryGP4U/lyHqWEkdoXrs8O36gmTGU/EsJYSIVILax
-0HZC3zkmxHgiN95ZvD+Y5Y9HDXAN04kT8O1V/QD4QUCP8MGXNrkQP/JZAnu5Y2D1
-Wrn/7Tft2ON3OpH5vUgR99bKR549LcRrYgxeTnci3xkOsnTjZRxEUJFQgVUCAwEA
-AQKCAgEAlBzIMbDLk+cW4rAG+WeTo9ZXygKKQqV/i7OM4j5GtudMTL1fxDwFLZTn
-kCaBhzo+8ynaxPa71ViA87n0HZFHFRnwXFq+XkgctyrCdwjnY9RAxktS/l5z/t1i
-EFTOFDWod1t6mbcpoegGF8RGmZDLpL7zR/+G5LBUU4RHXcrwBQli+s3x5imkwoon
-TLAbOeSz5BBgDlTpQtdhy7bWDa+ybya0QCtagBLyvBfb8rjQYrduzOQOBODw5xJr
-mGFUGWztqUf9swfjNpMD71EjXApk9EwUrXJgmBMiJYmdfpa6wH9kvFpyDo8J6gBr
-rPeJm5LMF3+vR6Bw0Bld3DtBB8PsTrockOdeJNHfnY54480e7AahfM5gkeuIYC4P
-E3CIbyAgpS8+OLpsXP207AOjFz1TLiOqyDUDsBqSMNEQ7QbIPTQw8UZ/o0vEoqEv
-RrJAvIAv0KUcFNUL0t6VX2OXbV+i+T85wPey3XqK9P8Zzc8NUEGJ2paDUkSuemKC
-nF9/siGaoBHXsNUkQuV9xYo4co66MHDGAx/OdUM5lPiUcrF/bR+ZUA3p1BLUQXbQ
-aJD9uKlvJ4ZRSwhR/fQc5UiVWl3l76k+0Ia/Ddd1ArphVhbvGPOsm3W7wJ6KukSk
-rBJh1PPV1HnA+icS2Wvu2kVdz9+39cQUYJIICO1uwWfPIb/R5MUCggEBAOSwkwXs
-jqewNc6X4mc19RGKIMUvOrRrQkOOY33pI+BjoqI8cl+NOHNB7F8/gVnHIfhZpOG6
-WD5St1/qlSPT1Nte+38P+woAp5mdclZyRgYb4MjZybZihUPIPVgUbxiZTDHy1Sw0
-kRgmvaV3ccvG9/9bBUKNr9Z+XySsIhq5DzY+yIZ33vhLB/0g05x2HVIsSlsRWzri
-lw0iX/v07bdIRUIv7QB8xcLY/23pIbHAXS8DaknN8YxpKtjilOnUWVp/dx4SIcJY
-6PtSBfPcwVJ2MA/xXWBvDP82/XxvbxKnjj8lvkbfqMC6jrXJBw3NT/he8b932IBb
-PwLGU4hoKvjXfUcCggEBAMCfa4N1KUXW0Mo3BcDk2Hk8zVYuTPDNTWg1Mxb46sn+
-HNVJKU0OrejM2hNNCwzJG7eVQBorJj5XefhaQFTvWoLKbf1YZuWKaQrRwKkHEqDi
-edplA2RkpUebeS4KYIr22rzu3ZrZqiJmRU5kAS9hwOzwFvnXUgGy7IoZKXhpo0HK
-xvwylb/C5FXh97tecDdH/5evB/DC515TIhPzUQ5tpT0oAl9MU7Pe1E/opzrD/0sR
-dqKVJcl9vBRbtcAIkCOVpLoA9T2VvisafZAJaRXc3ACFMceewgpVAtBCsWUtLfvW
-fHMHWfti5je19SWg7bUK56uHJ0vdAI+irkfpe1t0aoMCggEAR5cPL3eSYOREs9vQ
-QEcf5NG82H2kfv5kzAkzFCN7267VJryNgWQQG+SzPk3/DD/OXpSRjShsn3X9ecVR
-0tlpdRMS3//8snDqBqjHNlCnoxnvEHE9OB83YLS6n2wmKykyNSCzoxcBpPHbxITT
-1tr+n626w87fEOKWnkBUnND59h1JYO79mfTDF3bDR+Oh4iuDS2bvjEuKxc3RBmry
-T8IMDGA8bT6iGhEcRSgKKD7z7NfA2kHiL/ZsN2EXBOw43J+yhnNephx3MtXGj0S4
-MDxXZ2ZDuQCKrQpl6CJqPwi8+v+xxTYW+d5s9nNsBeIT+sieHTZDTEtEOnYjiDwz
-15p92QKCAQEAkMwGNQawpOhLgYcFEzC0LcbwEFWzztx10N0U77LkRD16jTZ3Do73
-WmYLlLC4mr7e0A0o58MB96EodfHaJD7dSi5Dqkt25hw6xEBS1H0Vms1EjlCa0S/7
-Mq4D1QFF+5B/c8EX4ty20S8R8FCqt2SDc1kz3FHpOo+20kUB8Jtwdveox1J7UXB+
-1rSL1lSyhEviLbMMhAbvh+90UYz5pJ/1s9hMmDi3PyJFdWBNvZYyZcrV5He7tRCI
-fsFGCfol6CoIby5jLA1Rq/M46jq4vQ+ObfGyLv3/nWa0O7u2wHjK9WIRoSKomJmK
-t9xXURb9Obfd2Qo7FwMl9dNzsWkpKuGDYwKCAQB+hiWu2C+0foJ4Z8auM1SK8be4
-waplfD7qIvONE/vtl+VAN+eVpz5kkQJfXiafktAHahgEdSx43bofR0Kv0/R7IRs3
-M1WYAr0w+19TXLXkuh2oYIbcoGrIN3HMmlKMv44xh/QUhRe337cCLejP0SESNN+k
-5wT91SbJwuCw/QsG3sD6NIMtCNWdcsAQq/ruhz7pQ/JZUFOueV0tkzbK+oNHWbNU
-lS99qjPaVCXZFlz/t2/89cljh9mtRjcfXIBfuTijN9sXNcLTXsfLsyHJ86eEbI2U
-o2JQ7Sjs10LpiwBbNNHBmulARgRONNMgik6tpNIS0tk9eke0lCX42bDFtAD4
------END RSA PRIVATE KEY-----
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
index 1fbb6580c389..306cc515c870 100644
--- a/tests/net/Android.bp
+++ b/tests/net/Android.bp
@@ -56,7 +56,7 @@ java_defaults {
"libutilscallstack",
"libziparchive",
"libz",
- "netd_aidl_interface-cpp",
+ "netd_aidl_interface-V2-cpp",
"libnetworkstatsfactorytestjni",
],
}
diff --git a/tools/incident_report/main.cpp b/tools/incident_report/main.cpp
index 17a3c7a91329..974166a11c2d 100644
--- a/tools/incident_report/main.cpp
+++ b/tools/incident_report/main.cpp
@@ -292,6 +292,7 @@ usage(FILE* out)
fprintf(out, "Take an incident report over adb (which must be in the PATH).\n");
fprintf(out, " -b output the incident report raw protobuf format\n");
fprintf(out, " -o OUTPUT the output file. OUTPUT may be '-' or omitted to use stdout\n");
+ fprintf(out, " -r REASON human readable description of why the report is taken.\n");
fprintf(out, " -s SERIAL sent to adb to choose which device, instead of $ANDROID_SERIAL\n");
fprintf(out, " -t output the incident report in pretty-printed text format\n");
fprintf(out, "\n");
@@ -307,13 +308,14 @@ main(int argc, char** argv)
enum { OUTPUT_TEXT, OUTPUT_PROTO } outputFormat = OUTPUT_TEXT;
const char* inFilename = NULL;
const char* outFilename = NULL;
+ const char* reason = NULL;
const char* adbSerial = NULL;
pid_t childPid = -1;
vector<string> sections;
const char* privacy = NULL;
int opt;
- while ((opt = getopt(argc, argv, "bhi:o:s:twp:")) != -1) {
+ while ((opt = getopt(argc, argv, "bhi:o:r:s:twp:")) != -1) {
switch (opt) {
case 'b':
outputFormat = OUTPUT_PROTO;
@@ -324,6 +326,9 @@ main(int argc, char** argv)
case 'o':
outFilename = optarg;
break;
+ case 'r':
+ reason = optarg;
+ break;
case 's':
adbSerial = optarg;
break;
@@ -376,7 +381,7 @@ main(int argc, char** argv)
dup2(pfd[1], STDOUT_FILENO);
close(pfd[0]);
close(pfd[1]);
- char const** args = (char const**)malloc(sizeof(char*) * (8 + sections.size()));
+ char const** args = (char const**)malloc(sizeof(char*) * (10 + sections.size()));
int argpos = 0;
args[argpos++] = "adb";
if (adbSerial != NULL) {
@@ -389,6 +394,10 @@ main(int argc, char** argv)
args[argpos++] = "-p";
args[argpos++] = privacy;
}
+ if (reason != NULL) {
+ args[argpos++] = "-r";
+ args[argpos++] = reason;
+ }
for (vector<string>::const_iterator it=sections.begin(); it!=sections.end(); it++) {
args[argpos++] = it->c_str();
}