summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp4
-rw-r--r--PREUPLOAD.cfg2
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java14
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java4
-rw-r--r--api/current.txt98
-rw-r--r--api/system-current.txt81
-rw-r--r--api/test-current.txt1000
-rw-r--r--api/test-lint-baseline.txt404
-rw-r--r--cmds/statsd/src/atoms.proto36
-rw-r--r--core/java/android/app/Activity.java47
-rw-r--r--core/java/android/app/ActivityOptions.java4
-rw-r--r--core/java/android/app/ActivityView.java501
-rw-r--r--core/java/android/app/Notification.java17
-rw-r--r--core/java/android/app/PendingIntent.java7
-rw-r--r--core/java/android/app/SystemServiceRegistry.java9
-rw-r--r--core/java/android/app/TaskEmbedder.java674
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java51
-rw-r--r--core/java/android/companion/CompanionDeviceManager.java37
-rw-r--r--core/java/android/companion/ICompanionDeviceManager.aidl2
-rw-r--r--core/java/android/content/Context.java7
-rw-r--r--core/java/android/content/ContextWrapper.java6
-rw-r--r--core/java/android/content/SyncStats.java2
-rw-r--r--core/java/android/net/nsd/NsdManager.java4
-rw-r--r--core/java/android/os/AsyncTask.java22
-rw-r--r--core/java/android/os/BasicShellCommandHandler.java320
-rw-r--r--core/java/android/os/BatteryStatsManager.java16
-rw-r--r--core/java/android/os/Binder.java59
-rw-r--r--core/java/android/os/Debug.java2
-rw-r--r--core/java/android/os/ShellCommand.java295
-rw-r--r--core/java/android/os/UserManager.java2
-rw-r--r--core/java/android/os/connectivity/CellularBatteryStats.java572
-rw-r--r--core/java/android/util/FeatureFlagUtils.java2
-rw-r--r--core/java/android/util/StatsEvent.java97
-rw-r--r--core/java/android/view/TextureView.java66
-rw-r--r--core/java/android/view/View.java27
-rw-r--r--core/java/android/view/ViewConfiguration.java8
-rw-r--r--core/java/android/view/WindowlessWindowManager.java5
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.aidl1
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java41
-rw-r--r--core/java/android/view/animation/AnimationUtils.java8
-rw-r--r--core/java/android/view/autofill/AutofillManager.java4
-rw-r--r--core/java/android/webkit/WebSettings.java7
-rw-r--r--core/java/android/widget/ListView.java4
-rw-r--r--core/java/android/widget/RelativeLayout.java2
-rw-r--r--core/java/com/android/internal/app/IAppOpsService.aidl12
-rw-r--r--core/java/com/android/internal/app/ResolverListAdapter.java3
-rw-r--r--core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java14
-rw-r--r--core/java/com/android/internal/os/BaseCommand.java6
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java20
-rw-r--r--core/java/com/android/internal/os/Zygote.java7
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBar.aidl19
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBarService.aidl1
-rw-r--r--core/java/com/android/internal/statusbar/RegisterStatusBarResult.java65
-rw-r--r--core/java/com/android/internal/util/CollectionUtils.java40
-rw-r--r--core/jni/Android.bp3
-rw-r--r--core/jni/android_media_AudioSystem.cpp4
-rw-r--r--core/jni/android_util_Process.cpp2
-rw-r--r--core/proto/android/server/activitymanagerservice.proto4
-rw-r--r--core/proto/android/server/windowcontainerthumbnail.proto (renamed from core/proto/android/server/appwindowthumbnail.proto)4
-rw-r--r--core/proto/android/server/windowmanagerservice.proto4
-rw-r--r--core/res/AndroidManifest.xml4
-rw-r--r--core/res/res/values/strings.xml4
-rw-r--r--core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java23
-rw-r--r--data/etc/privapp-permissions-platform.xml2
-rw-r--r--data/etc/services.core.protolog.json12
-rw-r--r--graphics/java/android/graphics/Paint.java12
-rw-r--r--libs/hwui/Android.bp1
-rw-r--r--libs/hwui/DeviceInfo.cpp101
-rw-r--r--libs/hwui/DeviceInfo.h26
-rw-r--r--libs/hwui/JankTracker.cpp14
-rw-r--r--libs/hwui/JankTracker.h3
-rw-r--r--libs/hwui/Properties.cpp1
-rw-r--r--libs/hwui/RenderProperties.h3
-rw-r--r--libs/hwui/renderthread/CacheManager.cpp9
-rw-r--r--libs/hwui/renderthread/CacheManager.h3
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp4
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp5
-rw-r--r--libs/hwui/renderthread/RenderThread.h1
-rw-r--r--libs/hwui/tests/unit/CacheManagerTests.cpp8
-rw-r--r--location/java/android/location/LocationManager.java4
-rw-r--r--location/java/android/location/LocationRequest.java17
-rw-r--r--media/java/android/media/Image.java2
-rw-r--r--media/java/android/media/MediaRouter2.java58
-rw-r--r--media/java/android/media/tv/tuner/Tuner.java78
-rw-r--r--media/jni/android_media_MediaCrypto.cpp18
-rw-r--r--media/jni/android_media_MediaDrm.cpp52
-rw-r--r--media/jni/android_media_MediaDrm.h22
-rw-r--r--media/jni/android_media_tv_Tuner.cpp49
-rw-r--r--media/jni/android_media_tv_Tuner.h18
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java217
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java17
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java15
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java252
-rw-r--r--packages/ExternalStorageProvider/res/values-af/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-am/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-ar/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-as/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-az/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-b+sr+Latn/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-be/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-bg/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-bn/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-bs/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-ca/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-cs/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-da/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-de/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-el/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-en-rAU/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-en-rCA/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-en-rGB/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-en-rIN/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-en-rXC/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-es-rUS/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-es/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-et/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-eu/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-fa/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-fi/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-fr-rCA/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-fr/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-gl/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-gu/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-hi/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-hr/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-hu/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-hy/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-in/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-is/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-it/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-iw/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-ja/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-ka/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-kk/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-km/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-kn/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-ko/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-ky/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-lo/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-lt/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-lv/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-mk/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-ml/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-mn/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-mr/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-ms/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-my/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-nb/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-ne/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-nl/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-or/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-pa/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-pl/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-pt-rBR/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-pt-rPT/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-pt/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-ro/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-ru/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-si/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-sk/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-sl/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-sq/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-sr/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-sv/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-sw/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-ta/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-te/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-th/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-tl/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-tr/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-uk/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-ur/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-uz/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-vi/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-zh-rCN/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-zh-rHK/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-zh-rTW/strings.xml8
-rw-r--r--packages/ExternalStorageProvider/res/values-zu/strings.xml8
-rw-r--r--packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java27
-rw-r--r--packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableData.java48
-rw-r--r--packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableResources.java11
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java4
-rw-r--r--packages/SystemUI/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java19
-rw-r--r--packages/SystemUI/src/com/android/keyguard/CarrierTextController.java12
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/CornerHandleView.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt74
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java129
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java238
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeService.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Recents.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java796
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java58
-rw-r--r--packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java49
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java92
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt48
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SwipeableView.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java179
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java134
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java237
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java55
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java143
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java57
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java251
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java8
-rw-r--r--packages/Tethering/Android.bp39
-rw-r--r--packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp (renamed from services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp)0
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java (renamed from services/core/java/com/android/server/connectivity/tethering/OffloadController.java)20
-rw-r--r--packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java (renamed from services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java)80
-rw-r--r--packages/Tethering/tests/unit/Android.bp2
-rw-r--r--packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java (renamed from tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java)14
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/SaveUi.java122
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java10
-rw-r--r--services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java3
-rw-r--r--services/core/java/com/android/server/AlarmManagerInternal.java8
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java31
-rw-r--r--services/core/java/com/android/server/AppStateTracker.java18
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java249
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java18
-rw-r--r--services/core/java/com/android/server/am/PendingIntentController.java3
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java15
-rw-r--r--services/core/java/com/android/server/am/UserController.java3
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java15
-rw-r--r--services/core/java/com/android/server/attention/AttentionManagerService.java69
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java24
-rw-r--r--services/core/java/com/android/server/location/GeofenceManager.java96
-rw-r--r--services/core/java/com/android/server/location/LocationBlacklist.java151
-rw-r--r--services/core/java/com/android/server/location/LocationSettingsStore.java461
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java23
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java4
-rw-r--r--services/core/java/com/android/server/notification/NotificationShellCmd.java78
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java15
-rw-r--r--services/core/java/com/android/server/pm/AppsFilter.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java9
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java5
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java167
-rw-r--r--services/core/java/com/android/server/wallpaper/GLHelper.java148
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java114
-rw-r--r--services/core/java/com/android/server/wm/ActivityDisplay.java3
-rw-r--r--services/core/java/com/android/server/wm/ActivityMetricsLogger.java21
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java112
-rw-r--r--services/core/java/com/android/server/wm/ActivityStack.java482
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java30
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartController.java13
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java7
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java29
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java4
-rw-r--r--services/core/java/com/android/server/wm/ConfigurationContainer.java6
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java14
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java77
-rw-r--r--services/core/java/com/android/server/wm/PinnedStackController.java9
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimation.java6
-rw-r--r--services/core/java/com/android/server/wm/RootActivityContainer.java21
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java2
-rw-r--r--services/core/java/com/android/server/wm/Task.java266
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioner.java38
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioningController.java4
-rw-r--r--services/core/java/com/android/server/wm/TaskRecord.java521
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java88
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java47
-rw-r--r--services/core/java/com/android/server/wm/WindowContainerThumbnail.java (renamed from services/core/java/com/android/server/wm/AppWindowThumbnail.java)87
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java28
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java12
-rw-r--r--services/core/jni/Android.bp2
-rw-r--r--services/core/jni/com_android_server_VibratorService.cpp24
-rw-r--r--services/java/com/android/server/SystemServer.java2
-rw-r--r--services/net/Android.bp1
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java34
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java130
-rw-r--r--services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java52
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java14
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java37
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java20
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java83
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java31
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskTests.java11
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java (renamed from services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java)10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java15
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java2
-rw-r--r--startop/view_compiler/Android.bp2
-rw-r--r--startop/view_compiler/dex_builder.cc93
-rw-r--r--startop/view_compiler/dex_builder.h48
-rw-r--r--telephony/java/android/telephony/AccessNetworkConstants.java1
-rw-r--r--telephony/java/android/telephony/CallQuality.java2
-rwxr-xr-xtelephony/java/android/telephony/CarrierConfigManager.java24
-rw-r--r--telephony/java/android/telephony/CbGeoUtils.java (renamed from telephony/java/com/android/internal/telephony/CbGeoUtils.java)46
-rw-r--r--telephony/java/android/telephony/ImsManager.java66
-rw-r--r--telephony/java/android/telephony/SmsCbMessage.java7
-rw-r--r--telephony/java/android/telephony/SmsManager.java5
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java11
-rw-r--r--telephony/java/android/telephony/SubscriptionPlan.java23
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java28
-rw-r--r--telephony/java/android/telephony/data/ApnSetting.java5
-rw-r--r--telephony/java/android/telephony/ims/ImsCallForwardInfo.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsCallProfile.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsCallSessionListener.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsConferenceState.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsException.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsExternalCallState.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsMmTelManager.java27
-rw-r--r--telephony/java/android/telephony/ims/ImsRcsManager.java142
-rw-r--r--telephony/java/android/telephony/ims/ImsReasonInfo.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsService.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsSsData.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsSsInfo.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsStreamMediaProfile.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsSuppServiceNotification.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsUtListener.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsVideoCallProvider.java2
-rw-r--r--telephony/java/android/telephony/ims/ProvisioningManager.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsUceAdapter.java102
-rw-r--r--telephony/java/android/telephony/ims/RegistrationManager.java40
-rw-r--r--telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl39
-rw-r--r--telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl29
-rw-r--r--telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java2
-rw-r--r--telephony/java/android/telephony/ims/feature/ImsFeature.java3
-rw-r--r--telephony/java/android/telephony/ims/feature/MmTelFeature.java2
-rw-r--r--telephony/java/android/telephony/ims/feature/RcsFeature.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java13
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java4
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java2
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsUtImplBase.java2
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java10
-rw-r--r--tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java7
-rw-r--r--tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java6
-rw-r--r--tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java6
-rw-r--r--tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java8
-rw-r--r--tests/Codegen/src/com/android/codegentest/SampleDataClass.java6
-rw-r--r--tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java6
-rw-r--r--tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java18
-rw-r--r--tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java6
-rw-r--r--tests/Gating/Android.bp17
-rw-r--r--tests/Gating/AndroidManifest.xml11
-rw-r--r--tests/Gating/AndroidTest.xml30
-rw-r--r--tests/Gating/src/com/android/compat/testing/DummyApi.java91
-rw-r--r--tests/Gating/src/com/android/tests/gating/GatingTest.java95
-rw-r--r--tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java27
-rw-r--r--tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java19
-rwxr-xr-xtools/apilint/apilint147
-rw-r--r--tools/apilint/apilint.py2353
-rwxr-xr-xtools/apilint/apilint_sha.sh4
-rwxr-xr-xtools/apilint/apilint_sha_system.sh23
-rwxr-xr-xtools/apilint/apilint_stats.sh7
-rw-r--r--tools/apilint/apilint_test.py414
-rw-r--r--tools/codegen/src/com/android/codegen/FieldInfo.kt4
-rw-r--r--tools/codegen/src/com/android/codegen/Generators.kt7
-rw-r--r--tools/codegen/src/com/android/codegen/SharedConstants.kt2
-rw-r--r--wifi/java/android/net/wifi/ISoftApCallback.aidl8
-rw-r--r--wifi/java/android/net/wifi/ScanResult.java1
-rw-r--r--wifi/java/android/net/wifi/SoftApInfo.aidl20
-rw-r--r--wifi/java/android/net/wifi/SoftApInfo.java211
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java19
-rw-r--r--wifi/java/android/net/wifi/rtt/ResponderConfig.java17
-rw-r--r--wifi/tests/src/android/net/wifi/SoftApInfoTest.java71
-rw-r--r--wifi/tests/src/android/net/wifi/WifiManagerTest.java28
421 files changed, 10711 insertions, 8185 deletions
diff --git a/Android.bp b/Android.bp
index a944bb937778..3721947fa4a6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -958,10 +958,10 @@ framework_docs_only_libs = [
metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
"--ignore-classes-on-classpath " +
- "--hide-package com.android.okhttp " +
- "--hide-package com.android.org.conscrypt --hide-package com.android.server " +
+ "--hide-package com.android.server " +
"--error UnhiddenSystemApi " +
"--hide RequiresPermission " +
+ "--hide CallbackInterface " +
"--hide MissingPermission --hide BroadcastBehavior " +
"--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
"--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index e731138ff40d..68311176a783 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,8 +1,6 @@
[Hook Scripts]
checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
-api_lint_hook = ${REPO_ROOT}/frameworks/base/tools/apilint/apilint_sha.sh ${PREUPLOAD_COMMIT}
-
strings_lint_hook = ${REPO_ROOT}/frameworks/base/tools/stringslint/stringslint_sha.sh ${PREUPLOAD_COMMIT}
hidden_api_txt_checksorted_hook = ${REPO_ROOT}/frameworks/base/tools/hiddenapi/checksorted_sha.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index eb22d0907525..4e96f5e0a205 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -57,11 +57,10 @@ import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
-import android.os.ResultReceiver;
import android.os.ServiceManager;
-import android.os.ShellCallback;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManagerInternal;
@@ -2690,12 +2689,15 @@ public class JobSchedulerService extends com.android.server.SystemService
}
@Override
- public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
- (new JobSchedulerShellCommand(JobSchedulerService.this)).exec(
- this, in, out, err, args, callback, resultReceiver);
+ protected int handleShellCommand(@NonNull ParcelFileDescriptor in,
+ @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
+ @NonNull String[] args) {
+ return (new JobSchedulerShellCommand(JobSchedulerService.this)).exec(
+ this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(),
+ args);
}
+
/**
* <b>For internal system user only!</b>
* Returns a list of all currently-executing jobs.
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
index 01d158ba9452..a5c6c0132fc8 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -20,13 +20,13 @@ import android.app.ActivityManager;
import android.app.AppGlobals;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.os.BasicShellCommandHandler;
import android.os.Binder;
-import android.os.ShellCommand;
import android.os.UserHandle;
import java.io.PrintWriter;
-public final class JobSchedulerShellCommand extends ShellCommand {
+public final class JobSchedulerShellCommand extends BasicShellCommandHandler {
public static final int CMD_ERR_NO_PACKAGE = -1000;
public static final int CMD_ERR_NO_JOB = -1001;
public static final int CMD_ERR_CONSTRAINTS = -1002;
diff --git a/api/current.txt b/api/current.txt
index 55983c86ee4b..0c30d0e4a87f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -34183,31 +34183,31 @@ package android.opengl {
package android.os {
- public abstract class AsyncTask<Params, Progress, Result> {
- ctor public AsyncTask();
- method public final boolean cancel(boolean);
- method @WorkerThread protected abstract Result doInBackground(Params...);
- method @MainThread public final android.os.AsyncTask<Params,Progress,Result> execute(Params...);
- method @MainThread public static void execute(Runnable);
- method @MainThread public final android.os.AsyncTask<Params,Progress,Result> executeOnExecutor(java.util.concurrent.Executor, Params...);
- method public final Result get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
- method public final Result get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
- method public final android.os.AsyncTask.Status getStatus();
- method public final boolean isCancelled();
- method @MainThread protected void onCancelled(Result);
- method @MainThread protected void onCancelled();
- method @MainThread protected void onPostExecute(Result);
- method @MainThread protected void onPreExecute();
- method @MainThread protected void onProgressUpdate(Progress...);
- method @WorkerThread protected final void publishProgress(Progress...);
- field public static final java.util.concurrent.Executor SERIAL_EXECUTOR;
- field public static final java.util.concurrent.Executor THREAD_POOL_EXECUTOR;
- }
-
- public enum AsyncTask.Status {
- enum_constant public static final android.os.AsyncTask.Status FINISHED;
- enum_constant public static final android.os.AsyncTask.Status PENDING;
- enum_constant public static final android.os.AsyncTask.Status RUNNING;
+ @Deprecated public abstract class AsyncTask<Params, Progress, Result> {
+ ctor @Deprecated public AsyncTask();
+ method @Deprecated public final boolean cancel(boolean);
+ method @Deprecated @WorkerThread protected abstract Result doInBackground(Params...);
+ method @Deprecated @MainThread public final android.os.AsyncTask<Params,Progress,Result> execute(Params...);
+ method @Deprecated @MainThread public static void execute(Runnable);
+ method @Deprecated @MainThread public final android.os.AsyncTask<Params,Progress,Result> executeOnExecutor(java.util.concurrent.Executor, Params...);
+ method @Deprecated public final Result get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+ method @Deprecated public final Result get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+ method @Deprecated public final android.os.AsyncTask.Status getStatus();
+ method @Deprecated public final boolean isCancelled();
+ method @Deprecated @MainThread protected void onCancelled(Result);
+ method @Deprecated @MainThread protected void onCancelled();
+ method @Deprecated @MainThread protected void onPostExecute(Result);
+ method @Deprecated @MainThread protected void onPreExecute();
+ method @Deprecated @MainThread protected void onProgressUpdate(Progress...);
+ method @Deprecated @WorkerThread protected final void publishProgress(Progress...);
+ field @Deprecated public static final java.util.concurrent.Executor SERIAL_EXECUTOR;
+ field @Deprecated public static final java.util.concurrent.Executor THREAD_POOL_EXECUTOR;
+ }
+
+ @Deprecated public enum AsyncTask.Status {
+ enum_constant @Deprecated public static final android.os.AsyncTask.Status FINISHED;
+ enum_constant @Deprecated public static final android.os.AsyncTask.Status PENDING;
+ enum_constant @Deprecated public static final android.os.AsyncTask.Status RUNNING;
}
public class BadParcelableException extends android.util.AndroidRuntimeException {
@@ -42916,6 +42916,7 @@ package android.system {
field public static final int IP_MULTICAST_TTL;
field public static final int IP_TOS;
field public static final int IP_TTL;
+ field public static final int MAP_ANONYMOUS;
field public static final int MAP_FIXED;
field public static final int MAP_PRIVATE;
field public static final int MAP_SHARED;
@@ -50390,34 +50391,34 @@ package android.view {
}
public class TextureView extends android.view.View {
- ctor public TextureView(android.content.Context);
- ctor public TextureView(android.content.Context, android.util.AttributeSet);
- ctor public TextureView(android.content.Context, android.util.AttributeSet, int);
- ctor public TextureView(android.content.Context, android.util.AttributeSet, int, int);
+ ctor public TextureView(@NonNull android.content.Context);
+ ctor public TextureView(@NonNull android.content.Context, @Nullable android.util.AttributeSet);
+ ctor public TextureView(@NonNull android.content.Context, @Nullable android.util.AttributeSet, int);
+ ctor public TextureView(@NonNull android.content.Context, @Nullable android.util.AttributeSet, int, int);
method public final void draw(android.graphics.Canvas);
- method public android.graphics.Bitmap getBitmap();
- method public android.graphics.Bitmap getBitmap(int, int);
- method public android.graphics.Bitmap getBitmap(android.graphics.Bitmap);
- method public android.graphics.SurfaceTexture getSurfaceTexture();
- method public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener();
- method public android.graphics.Matrix getTransform(android.graphics.Matrix);
+ method @Nullable public android.graphics.Bitmap getBitmap();
+ method @Nullable public android.graphics.Bitmap getBitmap(int, int);
+ method @NonNull public android.graphics.Bitmap getBitmap(@NonNull android.graphics.Bitmap);
+ method @Nullable public android.graphics.SurfaceTexture getSurfaceTexture();
+ method @Nullable public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener();
+ method @NonNull public android.graphics.Matrix getTransform(@Nullable android.graphics.Matrix);
method public boolean isAvailable();
- method public android.graphics.Canvas lockCanvas();
- method public android.graphics.Canvas lockCanvas(android.graphics.Rect);
+ method @Nullable public android.graphics.Canvas lockCanvas();
+ method @Nullable public android.graphics.Canvas lockCanvas(@Nullable android.graphics.Rect);
method protected final void onDraw(android.graphics.Canvas);
method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
method public void setOpaque(boolean);
- method public void setSurfaceTexture(android.graphics.SurfaceTexture);
- method public void setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener);
- method public void setTransform(android.graphics.Matrix);
- method public void unlockCanvasAndPost(android.graphics.Canvas);
+ method public void setSurfaceTexture(@NonNull android.graphics.SurfaceTexture);
+ method public void setSurfaceTextureListener(@Nullable android.view.TextureView.SurfaceTextureListener);
+ method public void setTransform(@Nullable android.graphics.Matrix);
+ method public void unlockCanvasAndPost(@NonNull android.graphics.Canvas);
}
public static interface TextureView.SurfaceTextureListener {
- method public void onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int);
- method public boolean onSurfaceTextureDestroyed(android.graphics.SurfaceTexture);
- method public void onSurfaceTextureSizeChanged(android.graphics.SurfaceTexture, int, int);
- method public void onSurfaceTextureUpdated(android.graphics.SurfaceTexture);
+ method public void onSurfaceTextureAvailable(@NonNull android.graphics.SurfaceTexture, int, int);
+ method public boolean onSurfaceTextureDestroyed(@NonNull android.graphics.SurfaceTexture);
+ method public void onSurfaceTextureSizeChanged(@NonNull android.graphics.SurfaceTexture, int, int);
+ method public void onSurfaceTextureUpdated(@NonNull android.graphics.SurfaceTexture);
}
public class TouchDelegate {
@@ -50677,7 +50678,7 @@ package android.view {
method public final int getScrollY();
method @android.view.ViewDebug.ExportedProperty(category="drawing") @ColorInt public int getSolidColor();
method @LayoutRes public int getSourceLayoutResId();
- method @android.view.ViewDebug.ExportedProperty(category="accessibility") @Nullable public final CharSequence getStateDescription();
+ method @android.view.ViewDebug.ExportedProperty(category="accessibility") @Nullable public CharSequence getStateDescription();
method public android.animation.StateListAnimator getStateListAnimator();
method protected int getSuggestedMinimumHeight();
method protected int getSuggestedMinimumWidth();
@@ -52646,10 +52647,12 @@ package android.view.accessibility {
field public static final int MOVEMENT_GRANULARITY_WORD = 2; // 0x2
}
- public static final class AccessibilityNodeInfo.AccessibilityAction {
+ public static final class AccessibilityNodeInfo.AccessibilityAction implements android.os.Parcelable {
ctor public AccessibilityNodeInfo.AccessibilityAction(int, @Nullable CharSequence);
+ method public int describeContents();
method public int getId();
method public CharSequence getLabel();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_ACCESSIBILITY_FOCUS;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_CLEAR_ACCESSIBILITY_FOCUS;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_CLEAR_FOCUS;
@@ -52687,6 +52690,7 @@ package android.view.accessibility {
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SET_TEXT;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SHOW_ON_SCREEN;
field public static final android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction ACTION_SHOW_TOOLTIP;
+ field @NonNull public static final android.os.Parcelable.Creator<android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction> CREATOR;
}
public static final class AccessibilityNodeInfo.CollectionInfo {
diff --git a/api/system-current.txt b/api/system-current.txt
index 9a241e836b88..463521c1d4fa 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1278,9 +1278,13 @@ package android.bluetooth {
method public boolean disableBLE();
method public boolean enableBLE();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean enableNoAutoConnect();
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean factoryReset();
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public long getDiscoveryEndMillis();
method public boolean isBleScanAlwaysAvailable();
method public boolean isLeEnabled();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean removeOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean setScanMode(int, int);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean setScanMode(int);
field public static final String ACTION_BLE_STATE_CHANGED = "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
field public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE = "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
}
@@ -1371,6 +1375,14 @@ package android.bluetooth.le {
}
+package android.companion {
+
+ public final class CompanionDeviceManager {
+ method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociated(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle);
+ }
+
+}
+
package android.content {
public class ContentProviderClient implements java.lang.AutoCloseable {
@@ -4755,6 +4767,21 @@ package android.net.wifi {
method @NonNull public android.net.wifi.SoftApConfiguration.Builder setWpa2Passphrase(@Nullable String);
}
+ public final class SoftApInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getBandwidth();
+ method public int getFrequency();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CHANNEL_WIDTH_160MHZ = 6; // 0x6
+ field public static final int CHANNEL_WIDTH_20MHZ = 2; // 0x2
+ field public static final int CHANNEL_WIDTH_20MHZ_NOHT = 1; // 0x1
+ field public static final int CHANNEL_WIDTH_40MHZ = 3; // 0x3
+ field public static final int CHANNEL_WIDTH_80MHZ = 4; // 0x4
+ field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 5; // 0x5
+ field public static final int CHANNEL_WIDTH_INVALID = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApInfo> CREATOR;
+ }
+
public final class WifiClient implements android.os.Parcelable {
method public int describeContents();
method @NonNull public android.net.MacAddress getMacAddress();
@@ -5132,6 +5159,7 @@ package android.net.wifi.rtt {
field public static final int CHANNEL_WIDTH_80MHZ = 2; // 0x2
field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4; // 0x4
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.rtt.ResponderConfig> CREATOR;
+ field public static final int PREAMBLE_HE = 3; // 0x3
field public static final int PREAMBLE_HT = 1; // 0x1
field public static final int PREAMBLE_LEGACY = 0; // 0x0
field public static final int PREAMBLE_VHT = 2; // 0x2
@@ -5241,6 +5269,7 @@ package android.os {
}
public class BatteryStatsManager {
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.CellularBatteryStats getCellularBatteryStats();
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.WifiBatteryStats getWifiBatteryStats();
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteFullWifiLockAcquiredFromSource(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteFullWifiLockReleasedFromSource(@NonNull android.os.WorkSource);
@@ -5748,6 +5777,26 @@ package android.os {
package android.os.connectivity {
+ public final class CellularBatteryStats implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getEnergyConsumedMaMillis();
+ method public long getIdleTimeMillis();
+ method public long getKernelActiveTimeMillis();
+ method public long getLoggingDurationMillis();
+ method public long getMonitoredRailChargeConsumedMaMillis();
+ method public long getNumBytesRx();
+ method public long getNumBytesTx();
+ method public long getNumPacketsRx();
+ method public long getNumPacketsTx();
+ method public long getRxTimeMillis();
+ method public long getSleepTimeMillis();
+ method @NonNull public long[] getTimeInRatMicros();
+ method @NonNull public long[] getTimeInRxSignalStrengthLevelMicros();
+ method @NonNull public long[] getTxTimeMillis();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.os.connectivity.CellularBatteryStats> CREATOR;
+ }
+
public final class WifiBatteryStats implements android.os.Parcelable {
method public int describeContents();
method public long getEnergyConsumedMaMillis();
@@ -7483,6 +7532,21 @@ package android.telephony {
method @NonNull public android.telephony.CarrierRestrictionRules.Builder setMultiSimPolicy(int);
}
+ public class CbGeoUtils {
+ }
+
+ public static interface CbGeoUtils.Geometry {
+ method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng);
+ }
+
+ public static class CbGeoUtils.LatLng {
+ ctor public CbGeoUtils.LatLng(double, double);
+ method public double distance(@NonNull android.telephony.CbGeoUtils.LatLng);
+ method @NonNull public android.telephony.CbGeoUtils.LatLng subtract(@NonNull android.telephony.CbGeoUtils.LatLng);
+ field public final double lat;
+ field public final double lng;
+ }
+
public abstract class CellBroadcastService extends android.app.Service {
ctor public CellBroadcastService();
method @CallSuper public android.os.IBinder onBind(@Nullable android.content.Intent);
@@ -8310,6 +8374,7 @@ package android.telephony {
method public int getGeographicalScope();
method @Nullable public String getLanguageCode();
method @NonNull public android.telephony.SmsCbLocation getLocation();
+ method public int getMaximumWaitingDuration();
method @Nullable public String getMessageBody();
method public int getMessageFormat();
method public int getMessagePriority();
@@ -8408,7 +8473,6 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableDataConnectivity();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean enableModemForSlot(int, boolean);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void enableVideoCalling(boolean);
- method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void factoryReset(int);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int);
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
@@ -8467,6 +8531,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig();
+ method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings();
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules);
@@ -9084,20 +9149,20 @@ package android.telephony.ims {
public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException;
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiModeSetting();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAdvancedCallingSettingEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.function.Consumer<java.lang.Boolean>, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isTtyOverVolteEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiRoamingSettingEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiSettingEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVtSettingEnabled();
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
@@ -9557,9 +9622,9 @@ package android.telephony.ims {
}
public interface RegistrationManager {
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
field public static final int REGISTRATION_STATE_NOT_REGISTERED = 0; // 0x0
field public static final int REGISTRATION_STATE_REGISTERED = 2; // 0x2
diff --git a/api/test-current.txt b/api/test-current.txt
index 495e57af1990..466320ba4403 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -643,6 +643,14 @@ package android.bluetooth {
}
+package android.companion {
+
+ public final class CompanionDeviceManager {
+ method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociated(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle);
+ }
+
+}
+
package android.content {
public final class AutofillOptions implements android.os.Parcelable {
@@ -2902,10 +2910,35 @@ package android.telecom {
package android.telephony {
public final class AccessNetworkConstants {
+ field public static final int TRANSPORT_TYPE_INVALID = -1; // 0xffffffff
field public static final int TRANSPORT_TYPE_WLAN = 2; // 0x2
field public static final int TRANSPORT_TYPE_WWAN = 1; // 0x1
}
+ public final class CallQuality implements android.os.Parcelable {
+ ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int);
+ method public int describeContents();
+ method public int getAverageRelativeJitter();
+ method public int getAverageRoundTripTime();
+ method public int getCallDuration();
+ method public int getCodecType();
+ method public int getDownlinkCallQualityLevel();
+ method public int getMaxRelativeJitter();
+ method public int getNumRtpPacketsNotReceived();
+ method public int getNumRtpPacketsReceived();
+ method public int getNumRtpPacketsTransmitted();
+ method public int getNumRtpPacketsTransmittedLost();
+ method public int getUplinkCallQualityLevel();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CALL_QUALITY_BAD = 4; // 0x4
+ field public static final int CALL_QUALITY_EXCELLENT = 0; // 0x0
+ field public static final int CALL_QUALITY_FAIR = 2; // 0x2
+ field public static final int CALL_QUALITY_GOOD = 1; // 0x1
+ field public static final int CALL_QUALITY_NOT_AVAILABLE = 5; // 0x5
+ field public static final int CALL_QUALITY_POOR = 3; // 0x3
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallQuality> CREATOR;
+ }
+
public class CarrierConfigManager {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void overrideConfig(int, @Nullable android.os.PersistableBundle);
}
@@ -3017,9 +3050,19 @@ package android.telephony {
field public static final int SMS_CATEGORY_STANDARD_SHORT_CODE = 2; // 0x2
}
+ public class SubscriptionManager {
+ field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
+ field @NonNull public static final android.net.Uri VT_ENABLED_CONTENT_URI;
+ field @NonNull public static final android.net.Uri WFC_ENABLED_CONTENT_URI;
+ field @NonNull public static final android.net.Uri WFC_MODE_CONTENT_URI;
+ field @NonNull public static final android.net.Uri WFC_ROAMING_ENABLED_CONTENT_URI;
+ field @NonNull public static final android.net.Uri WFC_ROAMING_MODE_CONTENT_URI;
+ }
+
public class TelephonyManager {
method public int checkCarrierPrivilegesForPackage(String);
method public int getCarrierIdListVersion();
+ method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getNetworkCountryIso(int);
method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
@@ -3043,6 +3086,963 @@ package android.telephony.emergency {
}
+package android.telephony.ims {
+
+ public final class ImsCallForwardInfo implements android.os.Parcelable {
+ ctor public ImsCallForwardInfo(int, int, int, int, @NonNull String, int);
+ method public int describeContents();
+ method public int getCondition();
+ method public String getNumber();
+ method public int getServiceClass();
+ method public int getStatus();
+ method public int getTimeSeconds();
+ method public int getToA();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CDIV_CF_REASON_ALL = 4; // 0x4
+ field public static final int CDIV_CF_REASON_ALL_CONDITIONAL = 5; // 0x5
+ field public static final int CDIV_CF_REASON_BUSY = 1; // 0x1
+ field public static final int CDIV_CF_REASON_NOT_LOGGED_IN = 6; // 0x6
+ field public static final int CDIV_CF_REASON_NOT_REACHABLE = 3; // 0x3
+ field public static final int CDIV_CF_REASON_NO_REPLY = 2; // 0x2
+ field public static final int CDIV_CF_REASON_UNCONDITIONAL = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallForwardInfo> CREATOR;
+ field public static final int STATUS_ACTIVE = 1; // 0x1
+ field public static final int STATUS_NOT_ACTIVE = 0; // 0x0
+ field public static final int TYPE_OF_ADDRESS_INTERNATIONAL = 145; // 0x91
+ field public static final int TYPE_OF_ADDRESS_UNKNOWN = 129; // 0x81
+ }
+
+ public final class ImsCallProfile implements android.os.Parcelable {
+ ctor public ImsCallProfile();
+ ctor public ImsCallProfile(int, int);
+ ctor public ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile);
+ method public int describeContents();
+ method public String getCallExtra(String);
+ method public String getCallExtra(String, String);
+ method public boolean getCallExtraBoolean(String);
+ method public boolean getCallExtraBoolean(String, boolean);
+ method public int getCallExtraInt(String);
+ method public int getCallExtraInt(String, int);
+ method public android.os.Bundle getCallExtras();
+ method public int getCallType();
+ method public static int getCallTypeFromVideoState(int);
+ method public int getCallerNumberVerificationStatus();
+ method public int getEmergencyCallRouting();
+ method public int getEmergencyServiceCategories();
+ method @NonNull public java.util.List<java.lang.String> getEmergencyUrns();
+ method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
+ method public int getRestrictCause();
+ method public int getServiceType();
+ method public static int getVideoStateFromCallType(int);
+ method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile);
+ method public boolean hasKnownUserIntentEmergency();
+ method public boolean isEmergencyCallTesting();
+ method public boolean isVideoCall();
+ method public boolean isVideoPaused();
+ method public static int presentationToOir(int);
+ method public void setCallExtra(String, String);
+ method public void setCallExtraBoolean(String, boolean);
+ method public void setCallExtraInt(String, int);
+ method public void setCallRestrictCause(int);
+ method public void setCallerNumberVerificationStatus(int);
+ method public void setEmergencyCallRouting(int);
+ method public void setEmergencyCallTesting(boolean);
+ method public void setEmergencyServiceCategories(int);
+ method public void setEmergencyUrns(@NonNull java.util.List<java.lang.String>);
+ method public void setHasKnownUserIntentEmergency(boolean);
+ method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
+ method public void updateCallType(android.telephony.ims.ImsCallProfile);
+ method public void updateMediaProfile(android.telephony.ims.ImsCallProfile);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CALL_RESTRICT_CAUSE_DISABLED = 2; // 0x2
+ field public static final int CALL_RESTRICT_CAUSE_HD = 3; // 0x3
+ field public static final int CALL_RESTRICT_CAUSE_NONE = 0; // 0x0
+ field public static final int CALL_RESTRICT_CAUSE_RAT = 1; // 0x1
+ field public static final int CALL_TYPE_VIDEO_N_VOICE = 3; // 0x3
+ field public static final int CALL_TYPE_VOICE = 2; // 0x2
+ field public static final int CALL_TYPE_VOICE_N_VIDEO = 1; // 0x1
+ field public static final int CALL_TYPE_VS = 8; // 0x8
+ field public static final int CALL_TYPE_VS_RX = 10; // 0xa
+ field public static final int CALL_TYPE_VS_TX = 9; // 0x9
+ field public static final int CALL_TYPE_VT = 4; // 0x4
+ field public static final int CALL_TYPE_VT_NODIR = 7; // 0x7
+ field public static final int CALL_TYPE_VT_RX = 6; // 0x6
+ field public static final int CALL_TYPE_VT_TX = 5; // 0x5
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallProfile> CREATOR;
+ field public static final int DIALSTRING_NORMAL = 0; // 0x0
+ field public static final int DIALSTRING_SS_CONF = 1; // 0x1
+ field public static final int DIALSTRING_USSD = 2; // 0x2
+ field public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
+ field public static final String EXTRA_ADDITIONAL_SIP_INVITE_FIELDS = "android.telephony.ims.extra.ADDITIONAL_SIP_INVITE_FIELDS";
+ field public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
+ field public static final String EXTRA_CHILD_NUMBER = "ChildNum";
+ field public static final String EXTRA_CNA = "cna";
+ field public static final String EXTRA_CNAP = "cnap";
+ field public static final String EXTRA_CODEC = "Codec";
+ field public static final String EXTRA_DIALSTRING = "dialstring";
+ field public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
+ field public static final String EXTRA_EMERGENCY_CALL = "e_call";
+ field public static final String EXTRA_IS_CALL_PULL = "CallPull";
+ field public static final String EXTRA_OI = "oi";
+ field public static final String EXTRA_OIR = "oir";
+ field public static final String EXTRA_REMOTE_URI = "remote_uri";
+ field public static final String EXTRA_USSD = "ussd";
+ field public static final int OIR_DEFAULT = 0; // 0x0
+ field public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2; // 0x2
+ field public static final int OIR_PRESENTATION_PAYPHONE = 4; // 0x4
+ field public static final int OIR_PRESENTATION_RESTRICTED = 1; // 0x1
+ field public static final int OIR_PRESENTATION_UNKNOWN = 3; // 0x3
+ field public static final int SERVICE_TYPE_EMERGENCY = 2; // 0x2
+ field public static final int SERVICE_TYPE_NONE = 0; // 0x0
+ field public static final int SERVICE_TYPE_NORMAL = 1; // 0x1
+ field public static final int VERIFICATION_STATUS_FAILED = 2; // 0x2
+ field public static final int VERIFICATION_STATUS_NOT_VERIFIED = 0; // 0x0
+ field public static final int VERIFICATION_STATUS_PASSED = 1; // 0x1
+ }
+
+ public class ImsCallSessionListener {
+ method public void callQualityChanged(@NonNull android.telephony.CallQuality);
+ method public void callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
+ method public void callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
+ method public void callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState);
+ method public void callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo);
+ method public void callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo);
+ method public void callSessionHeld(android.telephony.ims.ImsCallProfile);
+ method public void callSessionHoldFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionHoldReceived(android.telephony.ims.ImsCallProfile);
+ method public void callSessionInitiated(android.telephony.ims.ImsCallProfile);
+ method public void callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionInviteParticipantsRequestDelivered();
+ method public void callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionMayHandover(int, int);
+ method public void callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase);
+ method public void callSessionMergeFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
+ method public void callSessionMultipartyStateChanged(boolean);
+ method public void callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile);
+ method public void callSessionRemoveParticipantsRequestDelivered();
+ method public void callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionResumeFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionResumeReceived(android.telephony.ims.ImsCallProfile);
+ method public void callSessionResumed(android.telephony.ims.ImsCallProfile);
+ method public void callSessionRttAudioIndicatorChanged(@NonNull android.telephony.ims.ImsStreamMediaProfile);
+ method public void callSessionRttMessageReceived(String);
+ method public void callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile);
+ method public void callSessionRttModifyResponseReceived(int);
+ method public void callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification);
+ method public void callSessionTerminated(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionTtyModeReceived(int);
+ method public void callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionUpdateReceived(android.telephony.ims.ImsCallProfile);
+ method public void callSessionUpdated(android.telephony.ims.ImsCallProfile);
+ method public void callSessionUssdMessageReceived(int, String);
+ }
+
+ public final class ImsConferenceState implements android.os.Parcelable {
+ method public int describeContents();
+ method public static int getConnectionStateForStatus(String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsConferenceState> CREATOR;
+ field public static final String DISPLAY_TEXT = "display-text";
+ field public static final String ENDPOINT = "endpoint";
+ field public static final String SIP_STATUS_CODE = "sipstatuscode";
+ field public static final String STATUS = "status";
+ field public static final String STATUS_ALERTING = "alerting";
+ field public static final String STATUS_CONNECTED = "connected";
+ field public static final String STATUS_CONNECT_FAIL = "connect-fail";
+ field public static final String STATUS_DIALING_IN = "dialing-in";
+ field public static final String STATUS_DIALING_OUT = "dialing-out";
+ field public static final String STATUS_DISCONNECTED = "disconnected";
+ field public static final String STATUS_DISCONNECTING = "disconnecting";
+ field public static final String STATUS_MUTED_VIA_FOCUS = "muted-via-focus";
+ field public static final String STATUS_ON_HOLD = "on-hold";
+ field public static final String STATUS_PENDING = "pending";
+ field public static final String STATUS_SEND_ONLY = "sendonly";
+ field public static final String STATUS_SEND_RECV = "sendrecv";
+ field public static final String USER = "user";
+ field public final java.util.HashMap<java.lang.String,android.os.Bundle> mParticipants;
+ }
+
+ public final class ImsException extends java.lang.Exception {
+ ctor public ImsException(@Nullable String);
+ ctor public ImsException(@Nullable String, int);
+ ctor public ImsException(@Nullable String, int, @Nullable Throwable);
+ method public int getCode();
+ field public static final int CODE_ERROR_SERVICE_UNAVAILABLE = 1; // 0x1
+ field public static final int CODE_ERROR_UNSPECIFIED = 0; // 0x0
+ field public static final int CODE_ERROR_UNSUPPORTED_OPERATION = 2; // 0x2
+ }
+
+ public final class ImsExternalCallState implements android.os.Parcelable {
+ ctor public ImsExternalCallState(@NonNull String, @NonNull android.net.Uri, @Nullable android.net.Uri, boolean, int, int, boolean);
+ method public int describeContents();
+ method @NonNull public android.net.Uri getAddress();
+ method public int getCallId();
+ method public int getCallState();
+ method public int getCallType();
+ method @Nullable public android.net.Uri getLocalAddress();
+ method public boolean isCallHeld();
+ method public boolean isCallPullable();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CALL_STATE_CONFIRMED = 1; // 0x1
+ field public static final int CALL_STATE_TERMINATED = 2; // 0x2
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR;
+ }
+
+ public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
+ method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getFeatureState(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException;
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getVoWiFiModeSetting();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getVoWiFiRoamingModeSetting();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isAdvancedCallingSettingEnabled();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isAvailable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isTtyOverVolteEnabled();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isVoWiFiRoamingSettingEnabled();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isVoWiFiSettingEnabled();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isVtSettingEnabled();
+ method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiNonPersistent(boolean, int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingModeSetting(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSettingEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean);
+ method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterMmTelCapabilityCallback(@NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback);
+ field public static final int WIFI_MODE_CELLULAR_PREFERRED = 1; // 0x1
+ field public static final int WIFI_MODE_WIFI_ONLY = 0; // 0x0
+ field public static final int WIFI_MODE_WIFI_PREFERRED = 2; // 0x2
+ }
+
+ public static class ImsMmTelManager.CapabilityCallback {
+ ctor public ImsMmTelManager.CapabilityCallback();
+ method public void onCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);
+ }
+
+ @Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback {
+ ctor @Deprecated public ImsMmTelManager.RegistrationCallback();
+ }
+
+ public final class ImsReasonInfo implements android.os.Parcelable {
+ ctor public ImsReasonInfo(int, int, String);
+ method public int describeContents();
+ method public int getCode();
+ method public int getExtraCode();
+ method public String getExtraMessage();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CODE_ACCESS_CLASS_BLOCKED = 1512; // 0x5e8
+ field public static final int CODE_ANSWERED_ELSEWHERE = 1014; // 0x3f6
+ field public static final int CODE_BLACKLISTED_CALL_ID = 506; // 0x1fa
+ field public static final int CODE_CALL_BARRED = 240; // 0xf0
+ field public static final int CODE_CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE = 1100; // 0x44c
+ field public static final int CODE_CALL_END_CAUSE_CALL_PULL = 1016; // 0x3f8
+ field public static final int CODE_CALL_PULL_OUT_OF_SYNC = 1015; // 0x3f7
+ field public static final int CODE_DATA_DISABLED = 1406; // 0x57e
+ field public static final int CODE_DATA_LIMIT_REACHED = 1405; // 0x57d
+ field public static final int CODE_DIAL_MODIFIED_TO_DIAL = 246; // 0xf6
+ field public static final int CODE_DIAL_MODIFIED_TO_DIAL_VIDEO = 247; // 0xf7
+ field public static final int CODE_DIAL_MODIFIED_TO_SS = 245; // 0xf5
+ field public static final int CODE_DIAL_MODIFIED_TO_USSD = 244; // 0xf4
+ field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_DIAL = 248; // 0xf8
+ field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO = 249; // 0xf9
+ field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_SS = 250; // 0xfa
+ field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_USSD = 251; // 0xfb
+ field public static final int CODE_ECBM_NOT_SUPPORTED = 901; // 0x385
+ field public static final int CODE_EMERGENCY_PERM_FAILURE = 364; // 0x16c
+ field public static final int CODE_EMERGENCY_TEMP_FAILURE = 363; // 0x16b
+ field public static final int CODE_EPDG_TUNNEL_ESTABLISH_FAILURE = 1400; // 0x578
+ field public static final int CODE_EPDG_TUNNEL_LOST_CONNECTION = 1402; // 0x57a
+ field public static final int CODE_EPDG_TUNNEL_REKEY_FAILURE = 1401; // 0x579
+ field public static final int CODE_FDN_BLOCKED = 241; // 0xf1
+ field public static final int CODE_IKEV2_AUTH_FAILURE = 1408; // 0x580
+ field public static final int CODE_IMEI_NOT_ACCEPTED = 243; // 0xf3
+ field public static final int CODE_IWLAN_DPD_FAILURE = 1300; // 0x514
+ field public static final int CODE_LOCAL_CALL_BUSY = 142; // 0x8e
+ field public static final int CODE_LOCAL_CALL_CS_RETRY_REQUIRED = 146; // 0x92
+ field public static final int CODE_LOCAL_CALL_DECLINE = 143; // 0x8f
+ field public static final int CODE_LOCAL_CALL_EXCEEDED = 141; // 0x8d
+ field public static final int CODE_LOCAL_CALL_RESOURCE_RESERVATION_FAILED = 145; // 0x91
+ field public static final int CODE_LOCAL_CALL_TERMINATED = 148; // 0x94
+ field public static final int CODE_LOCAL_CALL_VCC_ON_PROGRESSING = 144; // 0x90
+ field public static final int CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED = 147; // 0x93
+ field public static final int CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE = 108; // 0x6c
+ field public static final int CODE_LOCAL_HO_NOT_FEASIBLE = 149; // 0x95
+ field public static final int CODE_LOCAL_ILLEGAL_ARGUMENT = 101; // 0x65
+ field public static final int CODE_LOCAL_ILLEGAL_STATE = 102; // 0x66
+ field public static final int CODE_LOCAL_IMS_SERVICE_DOWN = 106; // 0x6a
+ field public static final int CODE_LOCAL_INTERNAL_ERROR = 103; // 0x67
+ field public static final int CODE_LOCAL_LOW_BATTERY = 112; // 0x70
+ field public static final int CODE_LOCAL_NETWORK_IP_CHANGED = 124; // 0x7c
+ field public static final int CODE_LOCAL_NETWORK_NO_LTE_COVERAGE = 122; // 0x7a
+ field public static final int CODE_LOCAL_NETWORK_NO_SERVICE = 121; // 0x79
+ field public static final int CODE_LOCAL_NETWORK_ROAMING = 123; // 0x7b
+ field public static final int CODE_LOCAL_NOT_REGISTERED = 132; // 0x84
+ field public static final int CODE_LOCAL_NO_PENDING_CALL = 107; // 0x6b
+ field public static final int CODE_LOCAL_POWER_OFF = 111; // 0x6f
+ field public static final int CODE_LOCAL_SERVICE_UNAVAILABLE = 131; // 0x83
+ field public static final int CODE_LOW_BATTERY = 505; // 0x1f9
+ field public static final int CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED = 1403; // 0x57b
+ field public static final int CODE_MEDIA_INIT_FAILED = 401; // 0x191
+ field public static final int CODE_MEDIA_NOT_ACCEPTABLE = 403; // 0x193
+ field public static final int CODE_MEDIA_NO_DATA = 402; // 0x192
+ field public static final int CODE_MEDIA_UNSPECIFIED = 404; // 0x194
+ field public static final int CODE_MULTIENDPOINT_NOT_SUPPORTED = 902; // 0x386
+ field public static final int CODE_NETWORK_DETACH = 1513; // 0x5e9
+ field public static final int CODE_NETWORK_REJECT = 1504; // 0x5e0
+ field public static final int CODE_NETWORK_RESP_TIMEOUT = 1503; // 0x5df
+ field public static final int CODE_NO_CSFB_IN_CS_ROAM = 1516; // 0x5ec
+ field public static final int CODE_NO_VALID_SIM = 1501; // 0x5dd
+ field public static final int CODE_OEM_CAUSE_1 = 61441; // 0xf001
+ field public static final int CODE_OEM_CAUSE_10 = 61450; // 0xf00a
+ field public static final int CODE_OEM_CAUSE_11 = 61451; // 0xf00b
+ field public static final int CODE_OEM_CAUSE_12 = 61452; // 0xf00c
+ field public static final int CODE_OEM_CAUSE_13 = 61453; // 0xf00d
+ field public static final int CODE_OEM_CAUSE_14 = 61454; // 0xf00e
+ field public static final int CODE_OEM_CAUSE_15 = 61455; // 0xf00f
+ field public static final int CODE_OEM_CAUSE_2 = 61442; // 0xf002
+ field public static final int CODE_OEM_CAUSE_3 = 61443; // 0xf003
+ field public static final int CODE_OEM_CAUSE_4 = 61444; // 0xf004
+ field public static final int CODE_OEM_CAUSE_5 = 61445; // 0xf005
+ field public static final int CODE_OEM_CAUSE_6 = 61446; // 0xf006
+ field public static final int CODE_OEM_CAUSE_7 = 61447; // 0xf007
+ field public static final int CODE_OEM_CAUSE_8 = 61448; // 0xf008
+ field public static final int CODE_OEM_CAUSE_9 = 61449; // 0xf009
+ field public static final int CODE_RADIO_ACCESS_FAILURE = 1505; // 0x5e1
+ field public static final int CODE_RADIO_INTERNAL_ERROR = 1502; // 0x5de
+ field public static final int CODE_RADIO_LINK_FAILURE = 1506; // 0x5e2
+ field public static final int CODE_RADIO_LINK_LOST = 1507; // 0x5e3
+ field public static final int CODE_RADIO_OFF = 1500; // 0x5dc
+ field public static final int CODE_RADIO_RELEASE_ABNORMAL = 1511; // 0x5e7
+ field public static final int CODE_RADIO_RELEASE_NORMAL = 1510; // 0x5e6
+ field public static final int CODE_RADIO_SETUP_FAILURE = 1509; // 0x5e5
+ field public static final int CODE_RADIO_UPLINK_FAILURE = 1508; // 0x5e4
+ field public static final int CODE_REGISTRATION_ERROR = 1000; // 0x3e8
+ field public static final int CODE_REJECTED_ELSEWHERE = 1017; // 0x3f9
+ field public static final int CODE_REJECT_1X_COLLISION = 1603; // 0x643
+ field public static final int CODE_REJECT_CALL_ON_OTHER_SUB = 1602; // 0x642
+ field public static final int CODE_REJECT_CALL_TYPE_NOT_ALLOWED = 1605; // 0x645
+ field public static final int CODE_REJECT_CONFERENCE_TTY_NOT_ALLOWED = 1617; // 0x651
+ field public static final int CODE_REJECT_INTERNAL_ERROR = 1612; // 0x64c
+ field public static final int CODE_REJECT_MAX_CALL_LIMIT_REACHED = 1608; // 0x648
+ field public static final int CODE_REJECT_ONGOING_CALL_SETUP = 1607; // 0x647
+ field public static final int CODE_REJECT_ONGOING_CALL_TRANSFER = 1611; // 0x64b
+ field public static final int CODE_REJECT_ONGOING_CALL_UPGRADE = 1616; // 0x650
+ field public static final int CODE_REJECT_ONGOING_CALL_WAITING_DISABLED = 1601; // 0x641
+ field public static final int CODE_REJECT_ONGOING_CONFERENCE_CALL = 1618; // 0x652
+ field public static final int CODE_REJECT_ONGOING_CS_CALL = 1621; // 0x655
+ field public static final int CODE_REJECT_ONGOING_E911_CALL = 1606; // 0x646
+ field public static final int CODE_REJECT_ONGOING_ENCRYPTED_CALL = 1620; // 0x654
+ field public static final int CODE_REJECT_ONGOING_HANDOVER = 1614; // 0x64e
+ field public static final int CODE_REJECT_QOS_FAILURE = 1613; // 0x64d
+ field public static final int CODE_REJECT_SERVICE_NOT_REGISTERED = 1604; // 0x644
+ field public static final int CODE_REJECT_UNKNOWN = 1600; // 0x640
+ field public static final int CODE_REJECT_UNSUPPORTED_SDP_HEADERS = 1610; // 0x64a
+ field public static final int CODE_REJECT_UNSUPPORTED_SIP_HEADERS = 1609; // 0x649
+ field public static final int CODE_REJECT_VT_AVPF_NOT_ALLOWED = 1619; // 0x653
+ field public static final int CODE_REJECT_VT_TTY_NOT_ALLOWED = 1615; // 0x64f
+ field public static final int CODE_REMOTE_CALL_DECLINE = 1404; // 0x57c
+ field public static final int CODE_SESSION_MODIFICATION_FAILED = 1517; // 0x5ed
+ field public static final int CODE_SIP_ALTERNATE_EMERGENCY_CALL = 1514; // 0x5ea
+ field public static final int CODE_SIP_AMBIGUOUS = 376; // 0x178
+ field public static final int CODE_SIP_BAD_ADDRESS = 337; // 0x151
+ field public static final int CODE_SIP_BAD_REQUEST = 331; // 0x14b
+ field public static final int CODE_SIP_BUSY = 338; // 0x152
+ field public static final int CODE_SIP_CALL_OR_TRANS_DOES_NOT_EXIST = 372; // 0x174
+ field public static final int CODE_SIP_CLIENT_ERROR = 342; // 0x156
+ field public static final int CODE_SIP_EXTENSION_REQUIRED = 370; // 0x172
+ field public static final int CODE_SIP_FORBIDDEN = 332; // 0x14c
+ field public static final int CODE_SIP_GLOBAL_ERROR = 362; // 0x16a
+ field public static final int CODE_SIP_INTERVAL_TOO_BRIEF = 371; // 0x173
+ field public static final int CODE_SIP_LOOP_DETECTED = 373; // 0x175
+ field public static final int CODE_SIP_METHOD_NOT_ALLOWED = 366; // 0x16e
+ field public static final int CODE_SIP_NOT_ACCEPTABLE = 340; // 0x154
+ field public static final int CODE_SIP_NOT_FOUND = 333; // 0x14d
+ field public static final int CODE_SIP_NOT_REACHABLE = 341; // 0x155
+ field public static final int CODE_SIP_NOT_SUPPORTED = 334; // 0x14e
+ field public static final int CODE_SIP_PROXY_AUTHENTICATION_REQUIRED = 367; // 0x16f
+ field public static final int CODE_SIP_REDIRECTED = 321; // 0x141
+ field public static final int CODE_SIP_REQUEST_CANCELLED = 339; // 0x153
+ field public static final int CODE_SIP_REQUEST_ENTITY_TOO_LARGE = 368; // 0x170
+ field public static final int CODE_SIP_REQUEST_PENDING = 377; // 0x179
+ field public static final int CODE_SIP_REQUEST_TIMEOUT = 335; // 0x14f
+ field public static final int CODE_SIP_REQUEST_URI_TOO_LARGE = 369; // 0x171
+ field public static final int CODE_SIP_SERVER_ERROR = 354; // 0x162
+ field public static final int CODE_SIP_SERVER_INTERNAL_ERROR = 351; // 0x15f
+ field public static final int CODE_SIP_SERVER_TIMEOUT = 353; // 0x161
+ field public static final int CODE_SIP_SERVICE_UNAVAILABLE = 352; // 0x160
+ field public static final int CODE_SIP_TEMPRARILY_UNAVAILABLE = 336; // 0x150
+ field public static final int CODE_SIP_TOO_MANY_HOPS = 374; // 0x176
+ field public static final int CODE_SIP_TRANSACTION_DOES_NOT_EXIST = 343; // 0x157
+ field public static final int CODE_SIP_UNDECIPHERABLE = 378; // 0x17a
+ field public static final int CODE_SIP_USER_MARKED_UNWANTED = 365; // 0x16d
+ field public static final int CODE_SIP_USER_REJECTED = 361; // 0x169
+ field public static final int CODE_SUPP_SVC_CANCELLED = 1202; // 0x4b2
+ field public static final int CODE_SUPP_SVC_FAILED = 1201; // 0x4b1
+ field public static final int CODE_SUPP_SVC_REINVITE_COLLISION = 1203; // 0x4b3
+ field public static final int CODE_TIMEOUT_1XX_WAITING = 201; // 0xc9
+ field public static final int CODE_TIMEOUT_NO_ANSWER = 202; // 0xca
+ field public static final int CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE = 203; // 0xcb
+ field public static final int CODE_UNSPECIFIED = 0; // 0x0
+ field public static final int CODE_USER_CANCELLED_SESSION_MODIFICATION = 512; // 0x200
+ field public static final int CODE_USER_DECLINE = 504; // 0x1f8
+ field public static final int CODE_USER_IGNORE = 503; // 0x1f7
+ field public static final int CODE_USER_NOANSWER = 502; // 0x1f6
+ field public static final int CODE_USER_REJECTED_SESSION_MODIFICATION = 511; // 0x1ff
+ field public static final int CODE_USER_TERMINATED = 501; // 0x1f5
+ field public static final int CODE_USER_TERMINATED_BY_REMOTE = 510; // 0x1fe
+ field public static final int CODE_UT_CB_PASSWORD_MISMATCH = 821; // 0x335
+ field public static final int CODE_UT_NETWORK_ERROR = 804; // 0x324
+ field public static final int CODE_UT_NOT_SUPPORTED = 801; // 0x321
+ field public static final int CODE_UT_OPERATION_NOT_ALLOWED = 803; // 0x323
+ field public static final int CODE_UT_SERVICE_UNAVAILABLE = 802; // 0x322
+ field public static final int CODE_UT_SS_MODIFIED_TO_DIAL = 822; // 0x336
+ field public static final int CODE_UT_SS_MODIFIED_TO_DIAL_VIDEO = 825; // 0x339
+ field public static final int CODE_UT_SS_MODIFIED_TO_SS = 824; // 0x338
+ field public static final int CODE_UT_SS_MODIFIED_TO_USSD = 823; // 0x337
+ field public static final int CODE_WIFI_LOST = 1407; // 0x57f
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsReasonInfo> CREATOR;
+ field public static final int EXTRA_CODE_CALL_RETRY_BY_SETTINGS = 3; // 0x3
+ field public static final int EXTRA_CODE_CALL_RETRY_NORMAL = 1; // 0x1
+ field public static final int EXTRA_CODE_CALL_RETRY_SILENT_REDIAL = 2; // 0x2
+ field public static final String EXTRA_MSG_SERVICE_NOT_AUTHORIZED = "Forbidden. Not Authorized for Service";
+ }
+
+ public class ImsService extends android.app.Service {
+ ctor public ImsService();
+ method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int);
+ method public android.telephony.ims.feature.RcsFeature createRcsFeature(int);
+ method public void disableIms(int);
+ method public void enableIms(int);
+ method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
+ method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
+ method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException;
+ method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures();
+ method public void readyForFeatureCreation();
+ }
+
+ public final class ImsSsData implements android.os.Parcelable {
+ ctor public ImsSsData(int, int, int, int, int);
+ method public int describeContents();
+ method @Nullable public java.util.List<android.telephony.ims.ImsCallForwardInfo> getCallForwardInfo();
+ method public int getRequestType();
+ method public int getResult();
+ method public int getServiceClass();
+ method public int getServiceType();
+ method @NonNull public java.util.List<android.telephony.ims.ImsSsInfo> getSuppServiceInfo();
+ method public int getTeleserviceType();
+ method public boolean isTypeBarring();
+ method public boolean isTypeCf();
+ method public boolean isTypeClip();
+ method public boolean isTypeClir();
+ method public boolean isTypeColp();
+ method public boolean isTypeColr();
+ method public boolean isTypeCw();
+ method public boolean isTypeIcb();
+ method public boolean isTypeInterrogation();
+ method public boolean isTypeUnConditional();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsData> CREATOR;
+ field public static final int RESULT_SUCCESS = 0; // 0x0
+ field public static final int SERVICE_CLASS_DATA = 2; // 0x2
+ field public static final int SERVICE_CLASS_DATA_CIRCUIT_ASYNC = 32; // 0x20
+ field public static final int SERVICE_CLASS_DATA_CIRCUIT_SYNC = 16; // 0x10
+ field public static final int SERVICE_CLASS_DATA_PACKET_ACCESS = 64; // 0x40
+ field public static final int SERVICE_CLASS_DATA_PAD = 128; // 0x80
+ field public static final int SERVICE_CLASS_FAX = 4; // 0x4
+ field public static final int SERVICE_CLASS_NONE = 0; // 0x0
+ field public static final int SERVICE_CLASS_SMS = 8; // 0x8
+ field public static final int SERVICE_CLASS_VOICE = 1; // 0x1
+ field public static final int SS_ACTIVATION = 0; // 0x0
+ field public static final int SS_ALL_BARRING = 18; // 0x12
+ field public static final int SS_ALL_DATA_TELESERVICES = 3; // 0x3
+ field public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5; // 0x5
+ field public static final int SS_ALL_TELESEVICES = 1; // 0x1
+ field public static final int SS_ALL_TELE_AND_BEARER_SERVICES = 0; // 0x0
+ field public static final int SS_BAIC = 16; // 0x10
+ field public static final int SS_BAIC_ROAMING = 17; // 0x11
+ field public static final int SS_BAOC = 13; // 0xd
+ field public static final int SS_BAOIC = 14; // 0xe
+ field public static final int SS_BAOIC_EXC_HOME = 15; // 0xf
+ field public static final int SS_CFU = 0; // 0x0
+ field public static final int SS_CFUT = 6; // 0x6
+ field public static final int SS_CF_ALL = 4; // 0x4
+ field public static final int SS_CF_ALL_CONDITIONAL = 5; // 0x5
+ field public static final int SS_CF_BUSY = 1; // 0x1
+ field public static final int SS_CF_NOT_REACHABLE = 3; // 0x3
+ field public static final int SS_CF_NO_REPLY = 2; // 0x2
+ field public static final int SS_CLIP = 7; // 0x7
+ field public static final int SS_CLIR = 8; // 0x8
+ field public static final int SS_CNAP = 11; // 0xb
+ field public static final int SS_COLP = 9; // 0x9
+ field public static final int SS_COLR = 10; // 0xa
+ field public static final int SS_DEACTIVATION = 1; // 0x1
+ field public static final int SS_ERASURE = 4; // 0x4
+ field public static final int SS_INCOMING_BARRING = 20; // 0x14
+ field public static final int SS_INCOMING_BARRING_ANONYMOUS = 22; // 0x16
+ field public static final int SS_INCOMING_BARRING_DN = 21; // 0x15
+ field public static final int SS_INTERROGATION = 2; // 0x2
+ field public static final int SS_OUTGOING_BARRING = 19; // 0x13
+ field public static final int SS_REGISTRATION = 3; // 0x3
+ field public static final int SS_SMS_SERVICES = 4; // 0x4
+ field public static final int SS_TELEPHONY = 2; // 0x2
+ field public static final int SS_WAIT = 12; // 0xc
+ }
+
+ public static final class ImsSsData.Builder {
+ ctor public ImsSsData.Builder(int, int, int, int, int);
+ method @NonNull public android.telephony.ims.ImsSsData build();
+ method @NonNull public android.telephony.ims.ImsSsData.Builder setCallForwardingInfo(@NonNull java.util.List<android.telephony.ims.ImsCallForwardInfo>);
+ method @NonNull public android.telephony.ims.ImsSsData.Builder setSuppServiceInfo(@NonNull java.util.List<android.telephony.ims.ImsSsInfo>);
+ }
+
+ public final class ImsSsInfo implements android.os.Parcelable {
+ ctor @Deprecated public ImsSsInfo(int, @Nullable String);
+ method public int describeContents();
+ method public int getClirInterrogationStatus();
+ method public int getClirOutgoingState();
+ method @Deprecated public String getIcbNum();
+ method @Nullable public String getIncomingCommunicationBarringNumber();
+ method public int getProvisionStatus();
+ method public int getStatus();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CLIR_OUTGOING_DEFAULT = 0; // 0x0
+ field public static final int CLIR_OUTGOING_INVOCATION = 1; // 0x1
+ field public static final int CLIR_OUTGOING_SUPPRESSION = 2; // 0x2
+ field public static final int CLIR_STATUS_NOT_PROVISIONED = 0; // 0x0
+ field public static final int CLIR_STATUS_PROVISIONED_PERMANENT = 1; // 0x1
+ field public static final int CLIR_STATUS_TEMPORARILY_ALLOWED = 4; // 0x4
+ field public static final int CLIR_STATUS_TEMPORARILY_RESTRICTED = 3; // 0x3
+ field public static final int CLIR_STATUS_UNKNOWN = 2; // 0x2
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsInfo> CREATOR;
+ field public static final int DISABLED = 0; // 0x0
+ field public static final int ENABLED = 1; // 0x1
+ field public static final int NOT_REGISTERED = -1; // 0xffffffff
+ field public static final int SERVICE_NOT_PROVISIONED = 0; // 0x0
+ field public static final int SERVICE_PROVISIONED = 1; // 0x1
+ field public static final int SERVICE_PROVISIONING_UNKNOWN = -1; // 0xffffffff
+ }
+
+ public static final class ImsSsInfo.Builder {
+ ctor public ImsSsInfo.Builder(int);
+ method @NonNull public android.telephony.ims.ImsSsInfo build();
+ method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirInterrogationStatus(int);
+ method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirOutgoingState(int);
+ method @NonNull public android.telephony.ims.ImsSsInfo.Builder setIncomingCommunicationBarringNumber(@NonNull String);
+ method @NonNull public android.telephony.ims.ImsSsInfo.Builder setProvisionStatus(int);
+ }
+
+ public final class ImsStreamMediaProfile implements android.os.Parcelable {
+ ctor public ImsStreamMediaProfile(int, int, int, int, int);
+ method public void copyFrom(android.telephony.ims.ImsStreamMediaProfile);
+ method public int describeContents();
+ method public int getAudioDirection();
+ method public int getAudioQuality();
+ method public int getRttMode();
+ method public int getVideoDirection();
+ method public int getVideoQuality();
+ method public boolean isReceivingRttAudio();
+ method public boolean isRttCall();
+ method public void setReceivingRttAudio(boolean);
+ method public void setRttMode(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int AUDIO_QUALITY_AMR = 1; // 0x1
+ field public static final int AUDIO_QUALITY_AMR_WB = 2; // 0x2
+ field public static final int AUDIO_QUALITY_EVRC = 4; // 0x4
+ field public static final int AUDIO_QUALITY_EVRC_B = 5; // 0x5
+ field public static final int AUDIO_QUALITY_EVRC_NW = 7; // 0x7
+ field public static final int AUDIO_QUALITY_EVRC_WB = 6; // 0x6
+ field public static final int AUDIO_QUALITY_EVS_FB = 20; // 0x14
+ field public static final int AUDIO_QUALITY_EVS_NB = 17; // 0x11
+ field public static final int AUDIO_QUALITY_EVS_SWB = 19; // 0x13
+ field public static final int AUDIO_QUALITY_EVS_WB = 18; // 0x12
+ field public static final int AUDIO_QUALITY_G711A = 13; // 0xd
+ field public static final int AUDIO_QUALITY_G711AB = 15; // 0xf
+ field public static final int AUDIO_QUALITY_G711U = 11; // 0xb
+ field public static final int AUDIO_QUALITY_G722 = 14; // 0xe
+ field public static final int AUDIO_QUALITY_G723 = 12; // 0xc
+ field public static final int AUDIO_QUALITY_G729 = 16; // 0x10
+ field public static final int AUDIO_QUALITY_GSM_EFR = 8; // 0x8
+ field public static final int AUDIO_QUALITY_GSM_FR = 9; // 0x9
+ field public static final int AUDIO_QUALITY_GSM_HR = 10; // 0xa
+ field public static final int AUDIO_QUALITY_NONE = 0; // 0x0
+ field public static final int AUDIO_QUALITY_QCELP13K = 3; // 0x3
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsStreamMediaProfile> CREATOR;
+ field public static final int DIRECTION_INACTIVE = 0; // 0x0
+ field public static final int DIRECTION_INVALID = -1; // 0xffffffff
+ field public static final int DIRECTION_RECEIVE = 1; // 0x1
+ field public static final int DIRECTION_SEND = 2; // 0x2
+ field public static final int DIRECTION_SEND_RECEIVE = 3; // 0x3
+ field public static final int RTT_MODE_DISABLED = 0; // 0x0
+ field public static final int RTT_MODE_FULL = 1; // 0x1
+ field public static final int VIDEO_QUALITY_NONE = 0; // 0x0
+ field public static final int VIDEO_QUALITY_QCIF = 1; // 0x1
+ field public static final int VIDEO_QUALITY_QVGA_LANDSCAPE = 2; // 0x2
+ field public static final int VIDEO_QUALITY_QVGA_PORTRAIT = 4; // 0x4
+ field public static final int VIDEO_QUALITY_VGA_LANDSCAPE = 8; // 0x8
+ field public static final int VIDEO_QUALITY_VGA_PORTRAIT = 16; // 0x10
+ }
+
+ public final class ImsSuppServiceNotification implements android.os.Parcelable {
+ ctor public ImsSuppServiceNotification(int, int, int, int, String, String[]);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSuppServiceNotification> CREATOR;
+ field public final int code;
+ field public final String[] history;
+ field public final int index;
+ field public final int notificationType;
+ field public final String number;
+ field public final int type;
+ }
+
+ public class ImsUtListener {
+ method public void onLineIdentificationSupplementaryServiceResponse(int, @NonNull android.telephony.ims.ImsSsInfo);
+ method public void onSupplementaryServiceIndication(android.telephony.ims.ImsSsData);
+ method public void onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]);
+ method public void onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]);
+ method public void onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]);
+ method @Deprecated public void onUtConfigurationQueried(int, android.os.Bundle);
+ method public void onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo);
+ method public void onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo);
+ method public void onUtConfigurationUpdated(int);
+ field @Deprecated public static final String BUNDLE_KEY_CLIR = "queryClir";
+ field @Deprecated public static final String BUNDLE_KEY_SSINFO = "imsSsInfo";
+ }
+
+ public abstract class ImsVideoCallProvider {
+ ctor public ImsVideoCallProvider();
+ method public void changeCallDataUsage(long);
+ method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities);
+ method public void changePeerDimensions(int, int);
+ method public void changeVideoQuality(int);
+ method public void handleCallSessionEvent(int);
+ method public abstract void onRequestCallDataUsage();
+ method public abstract void onRequestCameraCapabilities();
+ method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile);
+ method public abstract void onSendSessionModifyResponse(android.telecom.VideoProfile);
+ method public abstract void onSetCamera(String);
+ method public void onSetCamera(String, int);
+ method public abstract void onSetDeviceOrientation(int);
+ method public abstract void onSetDisplaySurface(android.view.Surface);
+ method public abstract void onSetPauseImage(android.net.Uri);
+ method public abstract void onSetPreviewSurface(android.view.Surface);
+ method public abstract void onSetZoom(float);
+ method public void receiveSessionModifyRequest(android.telecom.VideoProfile);
+ method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile);
+ }
+
+ public class ProvisioningManager {
+ method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public int getProvisioningIntValue(int);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public boolean getProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+ method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public String getProvisioningStringValue(int);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
+ field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b
+ field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a
+ field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0
+ field public static final int PROVISIONING_VALUE_ENABLED = 1; // 0x1
+ field public static final String STRING_QUERY_RESULT_ERROR_GENERIC = "STRING_QUERY_RESULT_ERROR_GENERIC";
+ field public static final String STRING_QUERY_RESULT_ERROR_NOT_READY = "STRING_QUERY_RESULT_ERROR_NOT_READY";
+ }
+
+ public static class ProvisioningManager.Callback {
+ ctor public ProvisioningManager.Callback();
+ method public void onProvisioningIntChanged(int, int);
+ method public void onProvisioningStringChanged(int, @NonNull String);
+ }
+
+ public interface RegistrationManager {
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
+ field public static final int REGISTRATION_STATE_NOT_REGISTERED = 0; // 0x0
+ field public static final int REGISTRATION_STATE_REGISTERED = 2; // 0x2
+ field public static final int REGISTRATION_STATE_REGISTERING = 1; // 0x1
+ }
+
+ public static class RegistrationManager.RegistrationCallback {
+ ctor public RegistrationManager.RegistrationCallback();
+ method public void onRegistered(int);
+ method public void onRegistering(int);
+ method public void onTechnologyChangeFailed(int, @Nullable android.telephony.ims.ImsReasonInfo);
+ method public void onUnregistered(@Nullable android.telephony.ims.ImsReasonInfo);
+ }
+
+}
+
+package android.telephony.ims.feature {
+
+ public final class CapabilityChangeRequest implements android.os.Parcelable {
+ method public void addCapabilitiesToDisableForTech(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+ method public void addCapabilitiesToEnableForTech(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+ method public int describeContents();
+ method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToDisable();
+ method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToEnable();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.feature.CapabilityChangeRequest> CREATOR;
+ }
+
+ public static class CapabilityChangeRequest.CapabilityPair {
+ ctor public CapabilityChangeRequest.CapabilityPair(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+ method @android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability public int getCapability();
+ method public int getRadioTech();
+ }
+
+ public abstract class ImsFeature {
+ ctor public ImsFeature();
+ method public abstract void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+ method public final int getSlotIndex();
+ method public abstract void onFeatureReady();
+ method public abstract void onFeatureRemoved();
+ method public final void setFeatureState(int);
+ field public static final int CAPABILITY_ERROR_GENERIC = -1; // 0xffffffff
+ field public static final int CAPABILITY_SUCCESS = 0; // 0x0
+ field public static final int FEATURE_EMERGENCY_MMTEL = 0; // 0x0
+ field public static final int FEATURE_MMTEL = 1; // 0x1
+ field public static final int FEATURE_RCS = 2; // 0x2
+ field public static final int STATE_INITIALIZING = 1; // 0x1
+ field public static final int STATE_READY = 2; // 0x2
+ field public static final int STATE_UNAVAILABLE = 0; // 0x0
+ }
+
+ @Deprecated public static class ImsFeature.Capabilities {
+ field @Deprecated protected int mCapabilities;
+ }
+
+ protected static class ImsFeature.CapabilityCallbackProxy {
+ method public void onChangeCapabilityConfigurationError(int, int, int);
+ }
+
+ public class MmTelFeature extends android.telephony.ims.feature.ImsFeature {
+ ctor public MmTelFeature();
+ method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+ method @Nullable public android.telephony.ims.ImsCallProfile createCallProfile(int, int);
+ method @Nullable public android.telephony.ims.stub.ImsCallSessionImplBase createCallSession(@NonNull android.telephony.ims.ImsCallProfile);
+ method @NonNull public android.telephony.ims.stub.ImsEcbmImplBase getEcbm();
+ method @NonNull public android.telephony.ims.stub.ImsMultiEndpointImplBase getMultiEndpoint();
+ method @NonNull public android.telephony.ims.stub.ImsSmsImplBase getSmsImplementation();
+ method @NonNull public android.telephony.ims.stub.ImsUtImplBase getUt();
+ method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);
+ method public final void notifyIncomingCall(@NonNull android.telephony.ims.stub.ImsCallSessionImplBase, @NonNull android.os.Bundle);
+ method public final void notifyRejectedCall(@NonNull android.telephony.ims.ImsCallProfile, @NonNull android.telephony.ims.ImsReasonInfo);
+ method public final void notifyVoiceMessageCountUpdate(int);
+ method public void onFeatureReady();
+ method public void onFeatureRemoved();
+ method public boolean queryCapabilityConfiguration(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+ method public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus();
+ method public void setUiTtyMode(int, @Nullable android.os.Message);
+ method @android.telephony.ims.feature.MmTelFeature.ProcessCallResult public int shouldProcessCall(@NonNull String[]);
+ field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";
+ field public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD";
+ field public static final int PROCESS_CALL_CSFB = 1; // 0x1
+ field public static final int PROCESS_CALL_IMS = 0; // 0x0
+ }
+
+ public static class MmTelFeature.MmTelCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities {
+ ctor public MmTelFeature.MmTelCapabilities();
+ ctor @Deprecated public MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities);
+ ctor public MmTelFeature.MmTelCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
+ method public final void addCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
+ method public final boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
+ method public final void removeCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
+ field public static final int CAPABILITY_TYPE_SMS = 8; // 0x8
+ field public static final int CAPABILITY_TYPE_UT = 4; // 0x4
+ field public static final int CAPABILITY_TYPE_VIDEO = 2; // 0x2
+ field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1
+ }
+
+ @IntDef(flag=true, value={android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_SMS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MmTelFeature.MmTelCapabilities.MmTelCapability {
+ }
+
+ @IntDef(flag=true, value={android.telephony.ims.feature.MmTelFeature.PROCESS_CALL_IMS, android.telephony.ims.feature.MmTelFeature.PROCESS_CALL_CSFB}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MmTelFeature.ProcessCallResult {
+ }
+
+ public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
+ ctor public RcsFeature();
+ method public void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+ method public void onFeatureReady();
+ method public void onFeatureRemoved();
+ }
+
+}
+
+package android.telephony.ims.stub {
+
+ public class ImsCallSessionImplBase implements java.lang.AutoCloseable {
+ ctor public ImsCallSessionImplBase();
+ method public void accept(int, android.telephony.ims.ImsStreamMediaProfile);
+ method public void close();
+ method public void deflect(String);
+ method public void extendToConference(String[]);
+ method public String getCallId();
+ method public android.telephony.ims.ImsCallProfile getCallProfile();
+ method public android.telephony.ims.ImsVideoCallProvider getImsVideoCallProvider();
+ method public android.telephony.ims.ImsCallProfile getLocalCallProfile();
+ method public String getProperty(String);
+ method public android.telephony.ims.ImsCallProfile getRemoteCallProfile();
+ method public int getState();
+ method public void hold(android.telephony.ims.ImsStreamMediaProfile);
+ method public void inviteParticipants(String[]);
+ method public boolean isInCall();
+ method public boolean isMultiparty();
+ method public void merge();
+ method public void reject(int);
+ method public void removeParticipants(String[]);
+ method public void resume(android.telephony.ims.ImsStreamMediaProfile);
+ method public void sendDtmf(char, android.os.Message);
+ method public void sendRttMessage(String);
+ method public void sendRttModifyRequest(android.telephony.ims.ImsCallProfile);
+ method public void sendRttModifyResponse(boolean);
+ method public void sendUssd(String);
+ method public void setListener(android.telephony.ims.ImsCallSessionListener);
+ method public void setMute(boolean);
+ method public void start(String, android.telephony.ims.ImsCallProfile);
+ method public void startConference(String[], android.telephony.ims.ImsCallProfile);
+ method public void startDtmf(char);
+ method public void stopDtmf();
+ method public void terminate(int);
+ method public void update(int, android.telephony.ims.ImsStreamMediaProfile);
+ field public static final int USSD_MODE_NOTIFY = 0; // 0x0
+ field public static final int USSD_MODE_REQUEST = 1; // 0x1
+ }
+
+ public static class ImsCallSessionImplBase.State {
+ method public static String toString(int);
+ field public static final int ESTABLISHED = 4; // 0x4
+ field public static final int ESTABLISHING = 3; // 0x3
+ field public static final int IDLE = 0; // 0x0
+ field public static final int INITIATED = 1; // 0x1
+ field public static final int INVALID = -1; // 0xffffffff
+ field public static final int NEGOTIATING = 2; // 0x2
+ field public static final int REESTABLISHING = 6; // 0x6
+ field public static final int RENEGOTIATING = 5; // 0x5
+ field public static final int TERMINATED = 8; // 0x8
+ field public static final int TERMINATING = 7; // 0x7
+ }
+
+ public class ImsConfigImplBase {
+ ctor public ImsConfigImplBase();
+ method public int getConfigInt(int);
+ method public String getConfigString(int);
+ method public final void notifyProvisionedValueChanged(int, int);
+ method public final void notifyProvisionedValueChanged(int, String);
+ method public int setConfig(int, int);
+ method public int setConfig(int, String);
+ field public static final int CONFIG_RESULT_FAILED = 1; // 0x1
+ field public static final int CONFIG_RESULT_SUCCESS = 0; // 0x0
+ field public static final int CONFIG_RESULT_UNKNOWN = -1; // 0xffffffff
+ }
+
+ public class ImsEcbmImplBase {
+ ctor public ImsEcbmImplBase();
+ method public final void enteredEcbm();
+ method public void exitEmergencyCallbackMode();
+ method public final void exitedEcbm();
+ }
+
+ public final class ImsFeatureConfiguration implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.util.Set<android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair> getServiceFeatures();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.stub.ImsFeatureConfiguration> CREATOR;
+ }
+
+ public static class ImsFeatureConfiguration.Builder {
+ ctor public ImsFeatureConfiguration.Builder();
+ method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int, int);
+ method public android.telephony.ims.stub.ImsFeatureConfiguration build();
+ }
+
+ public static final class ImsFeatureConfiguration.FeatureSlotPair {
+ ctor public ImsFeatureConfiguration.FeatureSlotPair(int, int);
+ field public final int featureType;
+ field public final int slotId;
+ }
+
+ public class ImsMultiEndpointImplBase {
+ ctor public ImsMultiEndpointImplBase();
+ method public final void onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>);
+ method public void requestImsExternalCallStateInfo();
+ }
+
+ public class ImsRegistrationImplBase {
+ ctor public ImsRegistrationImplBase();
+ method public final void onDeregistered(android.telephony.ims.ImsReasonInfo);
+ method public final void onRegistered(int);
+ method public final void onRegistering(int);
+ method public final void onSubscriberAssociatedUriChanged(android.net.Uri[]);
+ method public final void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo);
+ field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1
+ field public static final int REGISTRATION_TECH_LTE = 0; // 0x0
+ field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff
+ }
+
+ public class ImsSmsImplBase {
+ ctor public ImsSmsImplBase();
+ method public void acknowledgeSms(int, @IntRange(from=0, to=65535) int, int);
+ method public void acknowledgeSmsReport(int, @IntRange(from=0, to=65535) int, int);
+ method public String getSmsFormat();
+ method public void onReady();
+ method @Deprecated public final void onSendSmsResult(int, @IntRange(from=0, to=65535) int, int, int) throws java.lang.RuntimeException;
+ method public final void onSendSmsResultError(int, @IntRange(from=0, to=65535) int, int, int, int) throws java.lang.RuntimeException;
+ method public final void onSendSmsResultSuccess(int, @IntRange(from=0, to=65535) int) throws java.lang.RuntimeException;
+ method public final void onSmsReceived(int, String, byte[]) throws java.lang.RuntimeException;
+ method @Deprecated public final void onSmsStatusReportReceived(int, @IntRange(from=0, to=65535) int, String, byte[]) throws java.lang.RuntimeException;
+ method public final void onSmsStatusReportReceived(int, String, byte[]) throws java.lang.RuntimeException;
+ method public void sendSms(int, @IntRange(from=0, to=65535) int, String, String, boolean, byte[]);
+ field public static final int DELIVER_STATUS_ERROR_GENERIC = 2; // 0x2
+ field public static final int DELIVER_STATUS_ERROR_NO_MEMORY = 3; // 0x3
+ field public static final int DELIVER_STATUS_ERROR_REQUEST_NOT_SUPPORTED = 4; // 0x4
+ field public static final int DELIVER_STATUS_OK = 1; // 0x1
+ field public static final int RESULT_NO_NETWORK_ERROR = -1; // 0xffffffff
+ field public static final int SEND_STATUS_ERROR = 2; // 0x2
+ field public static final int SEND_STATUS_ERROR_FALLBACK = 4; // 0x4
+ field public static final int SEND_STATUS_ERROR_RETRY = 3; // 0x3
+ field public static final int SEND_STATUS_OK = 1; // 0x1
+ field public static final int STATUS_REPORT_STATUS_ERROR = 2; // 0x2
+ field public static final int STATUS_REPORT_STATUS_OK = 1; // 0x1
+ }
+
+ public class ImsUtImplBase {
+ ctor public ImsUtImplBase();
+ method public void close();
+ method public int queryCallBarring(int);
+ method public int queryCallBarringForServiceClass(int, int);
+ method public int queryCallForward(int, String);
+ method public int queryCallWaiting();
+ method public int queryClip();
+ method public int queryClir();
+ method public int queryColp();
+ method public int queryColr();
+ method public void setListener(android.telephony.ims.ImsUtListener);
+ method public int transact(android.os.Bundle);
+ method public int updateCallBarring(int, int, String[]);
+ method public int updateCallBarringForServiceClass(int, int, String[], int);
+ method public int updateCallForward(int, int, String, int, int);
+ method public int updateCallWaiting(boolean, int);
+ method public int updateClip(boolean);
+ method public int updateClir(int);
+ method public int updateColp(boolean);
+ method public int updateColr(int);
+ }
+
+}
+
package android.telephony.mbms {
public static class DownloadRequest.Builder {
diff --git a/api/test-lint-baseline.txt b/api/test-lint-baseline.txt
index 9606413ff7cd..ba85ae66cd1a 100644
--- a/api/test-lint-baseline.txt
+++ b/api/test-lint-baseline.txt
@@ -7,6 +7,36 @@ AcronymName: android.app.NotificationChannel#setImportanceLockedByOEM(boolean):
ActionValue: android.location.Location#EXTRA_NO_GPS_LOCATION:
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_ADDITIONAL_CALL_INFO:
+ Inconsistent extra value; expected `android.telephony.ims.extra.ADDITIONAL_CALL_INFO`, was `AdditionalCallInfo`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CALL_RAT_TYPE:
+ Inconsistent extra value; expected `android.telephony.ims.extra.CALL_RAT_TYPE`, was `CallRadioTech`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CHILD_NUMBER:
+ Inconsistent extra value; expected `android.telephony.ims.extra.CHILD_NUMBER`, was `ChildNum`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CNA:
+ Inconsistent extra value; expected `android.telephony.ims.extra.CNA`, was `cna`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CNAP:
+ Inconsistent extra value; expected `android.telephony.ims.extra.CNAP`, was `cnap`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CODEC:
+ Inconsistent extra value; expected `android.telephony.ims.extra.CODEC`, was `Codec`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_DIALSTRING:
+ Inconsistent extra value; expected `android.telephony.ims.extra.DIALSTRING`, was `dialstring`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_DISPLAY_TEXT:
+ Inconsistent extra value; expected `android.telephony.ims.extra.DISPLAY_TEXT`, was `DisplayText`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_EMERGENCY_CALL:
+ Inconsistent extra value; expected `android.telephony.ims.extra.EMERGENCY_CALL`, was `e_call`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_IS_CALL_PULL:
+ Inconsistent extra value; expected `android.telephony.ims.extra.IS_CALL_PULL`, was `CallPull`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_OI:
+ Inconsistent extra value; expected `android.telephony.ims.extra.OI`, was `oi`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_OIR:
+ Inconsistent extra value; expected `android.telephony.ims.extra.OIR`, was `oir`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_REMOTE_URI:
+ Inconsistent extra value; expected `android.telephony.ims.extra.REMOTE_URI`, was `remote_uri`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_USSD:
+ Inconsistent extra value; expected `android.telephony.ims.extra.USSD`, was `ussd`
+ActionValue: android.telephony.ims.ImsReasonInfo#EXTRA_MSG_SERVICE_NOT_AUTHORIZED:
+ Inconsistent extra value; expected `android.telephony.ims.extra.MSG_SERVICE_NOT_AUTHORIZED`, was `Forbidden. Not Authorized for Service`
ActionValue: android.telephony.mbms.vendor.VendorUtils#ACTION_CLEANUP:
ActionValue: android.telephony.mbms.vendor.VendorUtils#ACTION_DOWNLOAD_RESULT_INTERNAL:
@@ -69,6 +99,14 @@ ArrayReturn: android.os.NativeHandle#getFileDescriptors():
ArrayReturn: android.security.keystore.AttestationUtils#attestDeviceIds(android.content.Context, int[], byte[]):
+ArrayReturn: android.telephony.ims.ImsUtListener#onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1:
+ Method parameter should be Collection<ImsSsInfo> (or subclass) instead of raw array; was `android.telephony.ims.ImsSsInfo[]`
+ArrayReturn: android.telephony.ims.ImsUtListener#onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]) parameter #1:
+ Method parameter should be Collection<ImsCallForwardInfo> (or subclass) instead of raw array; was `android.telephony.ims.ImsCallForwardInfo[]`
+ArrayReturn: android.telephony.ims.ImsUtListener#onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1:
+ Method parameter should be Collection<ImsSsInfo> (or subclass) instead of raw array; was `android.telephony.ims.ImsSsInfo[]`
+ArrayReturn: android.telephony.ims.stub.ImsRegistrationImplBase#onSubscriberAssociatedUriChanged(android.net.Uri[]) parameter #0:
+ Method parameter should be Collection<Uri> (or subclass) instead of raw array; was `android.net.Uri[]`
ArrayReturn: android.view.FocusFinder#sort(android.view.View[], int, int, android.view.ViewGroup, boolean) parameter #0:
ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions():
@@ -229,6 +267,8 @@ ConcreteCollection: android.service.autofill.InternalTransformation#batchApply(a
ConcreteCollection: android.service.autofill.UserData#getFieldClassificationAlgorithms():
+ConcreteCollection: android.telephony.ims.ImsConferenceState#mParticipants:
+ Field type is concrete collection (`java.util.HashMap`); must be higher-level interface
ContextFirst: android.os.VibrationEffect#get(android.net.Uri, android.content.Context) parameter #1:
@@ -297,6 +337,10 @@ ExecutorRegistration: android.os.RemoteCallback#RemoteCallback(android.os.Remote
ExecutorRegistration: android.permission.PermissionControllerManager#getAppPermissions(String, android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, android.os.Handler):
+ExecutorRegistration: android.telephony.ims.stub.ImsCallSessionImplBase#setListener(android.telephony.ims.ImsCallSessionListener):
+ Registration methods should have overload that accepts delivery Executor: `setListener`
+ExecutorRegistration: android.telephony.ims.stub.ImsUtImplBase#setListener(android.telephony.ims.ImsUtListener):
+ Registration methods should have overload that accepts delivery Executor: `setListener`
ExecutorRegistration: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener):
ExecutorRegistration: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener):
@@ -413,6 +457,10 @@ InterfaceConstant: android.telecom.PhoneAccountSuggestionService#SERVICE_INTERFA
+InternalField: android.telephony.ims.ImsConferenceState#mParticipants:
+ Internal field mParticipants must not be exposed
+
+
KotlinOperator: android.os.WorkSource#get(int):
@@ -423,6 +471,10 @@ ListenerInterface: android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListen
ListenerInterface: android.os.IncidentManager.AuthListener:
+ListenerInterface: android.telephony.ims.ImsCallSessionListener:
+ Listeners should be an interface, or otherwise renamed Callback: ImsCallSessionListener
+ListenerInterface: android.telephony.ims.ImsUtListener:
+ Listeners should be an interface, or otherwise renamed Callback: ImsUtListener
ListenerLast: android.hardware.camera2.CameraDevice#createCustomCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, int, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) parameter #4:
@@ -441,6 +493,20 @@ ManagerConstructor: android.content.pm.ShortcutManager#ShortcutManager(android.c
+ManagerLookup: android.telephony.ims.ImsMmTelManager#createForSubscriptionId(int):
+ Managers must always be obtained from Context (`createForSubscriptionId`)
+ManagerLookup: android.telephony.ims.ProvisioningManager#createForSubscriptionId(int):
+ Managers must always be obtained from Context (`createForSubscriptionId`)
+
+
+MethodNameTense: android.telephony.ims.feature.CapabilityChangeRequest#getCapabilitiesToEnable():
+ Unexpected tense; probably meant `enabled`, was `getCapabilitiesToEnable`
+
+
+MethodNameUnits: android.telephony.ims.ImsCallForwardInfo#getTimeSeconds():
+ Returned time values must be in milliseconds, was `getTimeSeconds`
+
+
MinMaxConstant: android.os.UserHandle#MIN_SECONDARY_USER_ID:
MinMaxConstant: android.view.autofill.AutofillManager#MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS:
@@ -1391,6 +1457,8 @@ MissingNullability: android.telecom.PhoneAccountSuggestionService#onBind(android
MissingNullability: android.telecom.PhoneAccountSuggestionService#onBind(android.content.Intent) parameter #0:
+MissingNullability: android.telephony.CallQuality#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `dest` in method `writeToParcel`
MissingNullability: android.telephony.DataSpecificRegistrationInfo#writeToParcel(android.os.Parcel, int) parameter #0:
MissingNullability: android.telephony.LteVopsSupportInfo#writeToParcel(android.os.Parcel, int) parameter #0:
@@ -1407,6 +1475,10 @@ MissingNullability: android.telephony.SmsManager#checkSmsShortCodeDestination(St
MissingNullability: android.telephony.TelephonyManager#checkCarrierPrivilegesForPackage(String) parameter #0:
+MissingNullability: android.telephony.TelephonyManager#getCarrierPackageNamesForIntent(android.content.Intent):
+ Missing nullability on method `getCarrierPackageNamesForIntent` return
+MissingNullability: android.telephony.TelephonyManager#getCarrierPackageNamesForIntent(android.content.Intent) parameter #0:
+ Missing nullability on parameter `intent` in method `getCarrierPackageNamesForIntent`
MissingNullability: android.telephony.TelephonyManager#getLine1AlphaTag():
MissingNullability: android.telephony.TelephonyManager#getRadioHalVersion():
@@ -1443,6 +1515,316 @@ MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(St
MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #8:
+MissingNullability: android.telephony.ims.ImsCallForwardInfo#getNumber():
+ Missing nullability on method `getNumber` return
+MissingNullability: android.telephony.ims.ImsCallForwardInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsCallProfile#ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile) parameter #2:
+ Missing nullability on parameter `callExtras` in method `ImsCallProfile`
+MissingNullability: android.telephony.ims.ImsCallProfile#ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile) parameter #3:
+ Missing nullability on parameter `mediaProfile` in method `ImsCallProfile`
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String):
+ Missing nullability on method `getCallExtra` return
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String) parameter #0:
+ Missing nullability on parameter `name` in method `getCallExtra`
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String, String):
+ Missing nullability on method `getCallExtra` return
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String, String) parameter #0:
+ Missing nullability on parameter `name` in method `getCallExtra`
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String, String) parameter #1:
+ Missing nullability on parameter `defaultValue` in method `getCallExtra`
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraBoolean(String) parameter #0:
+ Missing nullability on parameter `name` in method `getCallExtraBoolean`
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraBoolean(String, boolean) parameter #0:
+ Missing nullability on parameter `name` in method `getCallExtraBoolean`
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraInt(String) parameter #0:
+ Missing nullability on parameter `name` in method `getCallExtraInt`
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraInt(String, int) parameter #0:
+ Missing nullability on parameter `name` in method `getCallExtraInt`
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtras():
+ Missing nullability on method `getCallExtras` return
+MissingNullability: android.telephony.ims.ImsCallProfile#getMediaProfile():
+ Missing nullability on method `getMediaProfile` return
+MissingNullability: android.telephony.ims.ImsCallProfile#getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `callProfile` in method `getVideoStateFromImsCallProfile`
+MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtra(String, String) parameter #0:
+ Missing nullability on parameter `name` in method `setCallExtra`
+MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtra(String, String) parameter #1:
+ Missing nullability on parameter `value` in method `setCallExtra`
+MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtraBoolean(String, boolean) parameter #0:
+ Missing nullability on parameter `name` in method `setCallExtraBoolean`
+MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtraInt(String, int) parameter #0:
+ Missing nullability on parameter `name` in method `setCallExtraInt`
+MissingNullability: android.telephony.ims.ImsCallProfile#updateCallExtras(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `updateCallExtras`
+MissingNullability: android.telephony.ims.ImsCallProfile#updateCallType(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `updateCallType`
+MissingNullability: android.telephony.ims.ImsCallProfile#updateMediaProfile(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `updateMediaProfile`
+MissingNullability: android.telephony.ims.ImsCallProfile#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionConferenceExtendFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `newSession` in method `callSessionConferenceExtendReceived`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #1:
+ Missing nullability on parameter `profile` in method `callSessionConferenceExtendReceived`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `newSession` in method `callSessionConferenceExtended`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #1:
+ Missing nullability on parameter `profile` in method `callSessionConferenceExtended`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState) parameter #0:
+ Missing nullability on parameter `state` in method `callSessionConferenceStateUpdated`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo) parameter #2:
+ Missing nullability on parameter `reasonInfo` in method `callSessionHandover`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo) parameter #2:
+ Missing nullability on parameter `reasonInfo` in method `callSessionHandoverFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHeld(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `callSessionHeld`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHoldFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionHoldFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHoldReceived(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `callSessionHoldReceived`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionInitiated(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `callSessionInitiated`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionInitiatedFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionInviteParticipantsRequestFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase) parameter #0:
+ Missing nullability on parameter `newSession` in method `callSessionMergeComplete`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionMergeFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `newSession` in method `callSessionMergeStarted`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #1:
+ Missing nullability on parameter `profile` in method `callSessionMergeStarted`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `callSessionProgressing`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionRemoveParticipantsRequestFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionResumeFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionResumeFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionResumeReceived(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `callSessionResumeReceived`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionResumed(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `callSessionResumed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionRttMessageReceived(String) parameter #0:
+ Missing nullability on parameter `rttMessage` in method `callSessionRttMessageReceived`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `callProfile` in method `callSessionRttModifyRequestReceived`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification) parameter #0:
+ Missing nullability on parameter `suppSrvNotification` in method `callSessionSuppServiceReceived`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionTerminated(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionTerminated`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionUpdateFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUpdateReceived(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `callSessionUpdateReceived`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUpdated(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `callSessionUpdated`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUssdMessageReceived(int, String) parameter #1:
+ Missing nullability on parameter `ussdMessage` in method `callSessionUssdMessageReceived`
+MissingNullability: android.telephony.ims.ImsConferenceState#getConnectionStateForStatus(String) parameter #0:
+ Missing nullability on parameter `status` in method `getConnectionStateForStatus`
+MissingNullability: android.telephony.ims.ImsConferenceState#mParticipants:
+ Missing nullability on field `mParticipants` in class `class android.telephony.ims.ImsConferenceState`
+MissingNullability: android.telephony.ims.ImsConferenceState#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsExternalCallState#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsReasonInfo#ImsReasonInfo(int, int, String) parameter #2:
+ Missing nullability on parameter `extraMessage` in method `ImsReasonInfo`
+MissingNullability: android.telephony.ims.ImsReasonInfo#getExtraMessage():
+ Missing nullability on method `getExtraMessage` return
+MissingNullability: android.telephony.ims.ImsReasonInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsService#createMmTelFeature(int):
+ Missing nullability on method `createMmTelFeature` return
+MissingNullability: android.telephony.ims.ImsService#createRcsFeature(int):
+ Missing nullability on method `createRcsFeature` return
+MissingNullability: android.telephony.ims.ImsService#getConfig(int):
+ Missing nullability on method `getConfig` return
+MissingNullability: android.telephony.ims.ImsService#getRegistration(int):
+ Missing nullability on method `getRegistration` return
+MissingNullability: android.telephony.ims.ImsService#onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) parameter #0:
+ Missing nullability on parameter `c` in method `onUpdateSupportedImsFeatures`
+MissingNullability: android.telephony.ims.ImsService#querySupportedImsFeatures():
+ Missing nullability on method `querySupportedImsFeatures` return
+MissingNullability: android.telephony.ims.ImsSsData#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsSsInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsStreamMediaProfile#copyFrom(android.telephony.ims.ImsStreamMediaProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `copyFrom`
+MissingNullability: android.telephony.ims.ImsStreamMediaProfile#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsSuppServiceNotification#ImsSuppServiceNotification(int, int, int, int, String, String[]) parameter #4:
+ Missing nullability on parameter `number` in method `ImsSuppServiceNotification`
+MissingNullability: android.telephony.ims.ImsSuppServiceNotification#ImsSuppServiceNotification(int, int, int, int, String, String[]) parameter #5:
+ Missing nullability on parameter `history` in method `ImsSuppServiceNotification`
+MissingNullability: android.telephony.ims.ImsSuppServiceNotification#history:
+ Missing nullability on field `history` in class `class android.telephony.ims.ImsSuppServiceNotification`
+MissingNullability: android.telephony.ims.ImsSuppServiceNotification#number:
+ Missing nullability on field `number` in class `class android.telephony.ims.ImsSuppServiceNotification`
+MissingNullability: android.telephony.ims.ImsSuppServiceNotification#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsUtListener#onSupplementaryServiceIndication(android.telephony.ims.ImsSsData) parameter #0:
+ Missing nullability on parameter `ssData` in method `onSupplementaryServiceIndication`
+MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1:
+ Missing nullability on parameter `cbInfo` in method `onUtConfigurationCallBarringQueried`
+MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]) parameter #1:
+ Missing nullability on parameter `cfInfo` in method `onUtConfigurationCallForwardQueried`
+MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1:
+ Missing nullability on parameter `cwInfo` in method `onUtConfigurationCallWaitingQueried`
+MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationQueried(int, android.os.Bundle) parameter #1:
+ Missing nullability on parameter `configuration` in method `onUtConfigurationQueried`
+MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo) parameter #1:
+ Missing nullability on parameter `error` in method `onUtConfigurationQueryFailed`
+MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo) parameter #1:
+ Missing nullability on parameter `error` in method `onUtConfigurationUpdateFailed`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities) parameter #0:
+ Missing nullability on parameter `CameraCapabilities` in method `changeCameraCapabilities`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #0:
+ Missing nullability on parameter `fromProfile` in method `onSendSessionModifyRequest`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #1:
+ Missing nullability on parameter `toProfile` in method `onSendSessionModifyRequest`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSendSessionModifyResponse(android.telecom.VideoProfile) parameter #0:
+ Missing nullability on parameter `responseProfile` in method `onSendSessionModifyResponse`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetCamera(String) parameter #0:
+ Missing nullability on parameter `cameraId` in method `onSetCamera`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetCamera(String, int) parameter #0:
+ Missing nullability on parameter `cameraId` in method `onSetCamera`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetDisplaySurface(android.view.Surface) parameter #0:
+ Missing nullability on parameter `surface` in method `onSetDisplaySurface`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetPauseImage(android.net.Uri) parameter #0:
+ Missing nullability on parameter `uri` in method `onSetPauseImage`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetPreviewSurface(android.view.Surface) parameter #0:
+ Missing nullability on parameter `surface` in method `onSetPreviewSurface`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#receiveSessionModifyRequest(android.telecom.VideoProfile) parameter #0:
+ Missing nullability on parameter `VideoProfile` in method `receiveSessionModifyRequest`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #1:
+ Missing nullability on parameter `requestedProfile` in method `receiveSessionModifyResponse`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #2:
+ Missing nullability on parameter `responseProfile` in method `receiveSessionModifyResponse`
+MissingNullability: android.telephony.ims.feature.CapabilityChangeRequest#getCapabilitiesToDisable():
+ Missing nullability on method `getCapabilitiesToDisable` return
+MissingNullability: android.telephony.ims.feature.CapabilityChangeRequest#getCapabilitiesToEnable():
+ Missing nullability on method `getCapabilitiesToEnable` return
+MissingNullability: android.telephony.ims.feature.CapabilityChangeRequest#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `dest` in method `writeToParcel`
+MissingNullability: android.telephony.ims.feature.ImsFeature#changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy) parameter #0:
+ Missing nullability on parameter `request` in method `changeEnabledCapabilities`
+MissingNullability: android.telephony.ims.feature.ImsFeature#changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy) parameter #1:
+ Missing nullability on parameter `c` in method `changeEnabledCapabilities`
+MissingNullability: android.telephony.ims.feature.MmTelFeature#queryCapabilityStatus():
+ Missing nullability on method `queryCapabilityStatus` return
+MissingNullability: android.telephony.ims.feature.MmTelFeature.MmTelCapabilities#MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities) parameter #0:
+ Missing nullability on parameter `c` in method `MmTelCapabilities`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#accept(int, android.telephony.ims.ImsStreamMediaProfile) parameter #1:
+ Missing nullability on parameter `profile` in method `accept`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#deflect(String) parameter #0:
+ Missing nullability on parameter `deflectNumber` in method `deflect`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#extendToConference(String[]) parameter #0:
+ Missing nullability on parameter `participants` in method `extendToConference`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getCallId():
+ Missing nullability on method `getCallId` return
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getCallProfile():
+ Missing nullability on method `getCallProfile` return
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getImsVideoCallProvider():
+ Missing nullability on method `getImsVideoCallProvider` return
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getLocalCallProfile():
+ Missing nullability on method `getLocalCallProfile` return
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getProperty(String):
+ Missing nullability on method `getProperty` return
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getProperty(String) parameter #0:
+ Missing nullability on parameter `name` in method `getProperty`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getRemoteCallProfile():
+ Missing nullability on method `getRemoteCallProfile` return
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#hold(android.telephony.ims.ImsStreamMediaProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `hold`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#inviteParticipants(String[]) parameter #0:
+ Missing nullability on parameter `participants` in method `inviteParticipants`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#removeParticipants(String[]) parameter #0:
+ Missing nullability on parameter `participants` in method `removeParticipants`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#resume(android.telephony.ims.ImsStreamMediaProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `resume`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendDtmf(char, android.os.Message) parameter #1:
+ Missing nullability on parameter `result` in method `sendDtmf`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendRttMessage(String) parameter #0:
+ Missing nullability on parameter `rttMessage` in method `sendRttMessage`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendRttModifyRequest(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `toProfile` in method `sendRttModifyRequest`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendUssd(String) parameter #0:
+ Missing nullability on parameter `ussdMessage` in method `sendUssd`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#setListener(android.telephony.ims.ImsCallSessionListener) parameter #0:
+ Missing nullability on parameter `listener` in method `setListener`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#start(String, android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `callee` in method `start`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#start(String, android.telephony.ims.ImsCallProfile) parameter #1:
+ Missing nullability on parameter `profile` in method `start`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#startConference(String[], android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `participants` in method `startConference`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#startConference(String[], android.telephony.ims.ImsCallProfile) parameter #1:
+ Missing nullability on parameter `profile` in method `startConference`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#update(int, android.telephony.ims.ImsStreamMediaProfile) parameter #1:
+ Missing nullability on parameter `profile` in method `update`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase.State#toString(int):
+ Missing nullability on method `toString` return
+MissingNullability: android.telephony.ims.stub.ImsConfigImplBase#getConfigString(int):
+ Missing nullability on method `getConfigString` return
+MissingNullability: android.telephony.ims.stub.ImsConfigImplBase#notifyProvisionedValueChanged(int, String) parameter #1:
+ Missing nullability on parameter `value` in method `notifyProvisionedValueChanged`
+MissingNullability: android.telephony.ims.stub.ImsConfigImplBase#setConfig(int, String) parameter #1:
+ Missing nullability on parameter `value` in method `setConfig`
+MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration#getServiceFeatures():
+ Missing nullability on method `getServiceFeatures` return
+MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `dest` in method `writeToParcel`
+MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration.Builder#addFeature(int, int):
+ Missing nullability on method `addFeature` return
+MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration.Builder#build():
+ Missing nullability on method `build` return
+MissingNullability: android.telephony.ims.stub.ImsMultiEndpointImplBase#onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>) parameter #0:
+ Missing nullability on parameter `externalCallDialogs` in method `onImsExternalCallStateUpdate`
+MissingNullability: android.telephony.ims.stub.ImsRegistrationImplBase#onDeregistered(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `info` in method `onDeregistered`
+MissingNullability: android.telephony.ims.stub.ImsRegistrationImplBase#onSubscriberAssociatedUriChanged(android.net.Uri[]) parameter #0:
+ Missing nullability on parameter `uris` in method `onSubscriberAssociatedUriChanged`
+MissingNullability: android.telephony.ims.stub.ImsRegistrationImplBase#onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo) parameter #1:
+ Missing nullability on parameter `info` in method `onTechnologyChangeFailed`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#getSmsFormat():
+ Missing nullability on method `getSmsFormat` return
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsReceived(int, String, byte[]) parameter #1:
+ Missing nullability on parameter `format` in method `onSmsReceived`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsReceived(int, String, byte[]) parameter #2:
+ Missing nullability on parameter `pdu` in method `onSmsReceived`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, String, byte[]) parameter #1:
+ Missing nullability on parameter `format` in method `onSmsStatusReportReceived`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, String, byte[]) parameter #2:
+ Missing nullability on parameter `pdu` in method `onSmsStatusReportReceived`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, int, String, byte[]) parameter #2:
+ Missing nullability on parameter `format` in method `onSmsStatusReportReceived`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, int, String, byte[]) parameter #3:
+ Missing nullability on parameter `pdu` in method `onSmsStatusReportReceived`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, String, String, boolean, byte[]) parameter #2:
+ Missing nullability on parameter `format` in method `sendSms`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, String, String, boolean, byte[]) parameter #3:
+ Missing nullability on parameter `smsc` in method `sendSms`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, String, String, boolean, byte[]) parameter #5:
+ Missing nullability on parameter `pdu` in method `sendSms`
+MissingNullability: android.telephony.ims.stub.ImsUtImplBase#queryCallForward(int, String) parameter #1:
+ Missing nullability on parameter `number` in method `queryCallForward`
+MissingNullability: android.telephony.ims.stub.ImsUtImplBase#setListener(android.telephony.ims.ImsUtListener) parameter #0:
+ Missing nullability on parameter `listener` in method `setListener`
+MissingNullability: android.telephony.ims.stub.ImsUtImplBase#transact(android.os.Bundle) parameter #0:
+ Missing nullability on parameter `ssInfo` in method `transact`
+MissingNullability: android.telephony.ims.stub.ImsUtImplBase#updateCallBarring(int, int, String[]) parameter #2:
+ Missing nullability on parameter `barrList` in method `updateCallBarring`
+MissingNullability: android.telephony.ims.stub.ImsUtImplBase#updateCallBarringForServiceClass(int, int, String[], int) parameter #2:
+ Missing nullability on parameter `barrList` in method `updateCallBarringForServiceClass`
+MissingNullability: android.telephony.ims.stub.ImsUtImplBase#updateCallForward(int, int, String, int, int) parameter #2:
+ Missing nullability on parameter `number` in method `updateCallForward`
MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String):
MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String) parameter #0:
@@ -1893,6 +2275,8 @@ NotCloseable: android.app.prediction.AppPredictor:
NotCloseable: android.os.HwParcel:
+NotCloseable: android.telephony.ims.stub.ImsUtImplBase:
+ Classes that release resources (close()) should implement AutoClosable and CloseGuard: class android.telephony.ims.stub.ImsUtImplBase
OnNameExpected: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.PrintWriter, String[]):
@@ -1905,6 +2289,22 @@ OnNameExpected: android.service.notification.NotificationAssistantService#attach
OnNameExpected: android.service.quicksettings.TileService#isQuickSettingsSupported():
+OnNameExpected: android.telephony.ims.ImsService#createMmTelFeature(int):
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.telephony.ims.ImsService#createRcsFeature(int):
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.telephony.ims.ImsService#disableIms(int):
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.telephony.ims.ImsService#enableIms(int):
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.telephony.ims.ImsService#getConfig(int):
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.telephony.ims.ImsService#getRegistration(int):
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.telephony.ims.ImsService#querySupportedImsFeatures():
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.telephony.ims.ImsService#readyForFeatureCreation():
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#dispose(int):
OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int):
@@ -2043,6 +2443,8 @@ RethrowRemoteException: android.os.HwBinder#transact(int, android.os.HwParcel, a
RethrowRemoteException: android.os.IHwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int):
+RethrowRemoteException: android.telephony.ims.ImsService#onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration):
+ Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause)
RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener):
RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener):
@@ -2121,6 +2523,8 @@ SamShouldBeLast: android.service.autofill.ImageTransformation#apply(android.serv
SamShouldBeLast: android.service.autofill.InternalTransformation#batchApply(android.service.autofill.ValueFinder, android.widget.RemoteViews, java.util.ArrayList<android.util.Pair<java.lang.Integer,android.service.autofill.InternalTransformation>>):
+SamShouldBeLast: android.telephony.ims.ImsMmTelManager#getFeatureState(java.util.function.Consumer<java.lang.Integer>, java.util.concurrent.Executor):
+ SAM-compatible parameters (such as parameter 1, "callback", in android.telephony.ims.ImsMmTelManager.getFeatureState) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.view.Choreographer#postCallback(int, Runnable, Object):
SamShouldBeLast: android.view.Choreographer#postCallbackDelayed(int, Runnable, Object, long):
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 8618d4ded817..c196c61a2b55 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -337,6 +337,8 @@ message Atom {
CameraActionEvent camera_action_event = 227;
AppCompatibilityChangeReported app_compatibility_change_reported =
228 [(allow_from_any_uid) = true];
+ PerfettoUploaded perfetto_uploaded =
+ 229 [(log_from_module) = "perfetto"];
}
// Pulled events will start at field 10000.
@@ -7239,3 +7241,37 @@ message AppCompatibilityChangeReported {
optional Source source = 4;
}
+
+/**
+ * Logged from
+ * external/perfetto/src/perfetto_cmd/perfetto_cmd.cc
+ */
+message PerfettoUploaded {
+ enum Event {
+ PERFETTO_UNDEFINED = 0;
+ PERFETTO_TRACE_BEGIN = 1;
+ PERFETTO_BACKGROUND_TRACE_BEGIN = 2;
+ PERFETTO_ON_CONNECT = 3;
+ PERFETTO_ON_TRACING_DISABLED = 4;
+ PERFETTO_UPLOAD_DROPBOX_BEGIN = 5;
+ PERFETTO_UPLOAD_DROPBOX_SUCCESS = 6;
+ PERFETTO_UPLOAD_DROPBOX_FAILURE = 7;
+ PERFETTO_UPLOAD_INCIDENT_BEGIN = 8;
+ PERFETTO_UPLOAD_INCIDENT_SUCCESS = 9;
+ PERFETTO_UPLOAD_INCIDENT_FAILURE = 10;
+ PERFETTO_FINALIZE_TRACE_AND_EXIT = 11;
+ PERFETTO_TRIGGER_BEGIN = 12;
+ PERFETTO_TRIGGER_SUCCESS = 13;
+ PERFETTO_TRIGGER_FAILURE = 14;
+ PERFETTO_HIT_GUARDRAILS = 15;
+ PERFETTO_ON_TIMEOUT = 16;
+ PERFETTO_NOT_UPLOADING_EMPTY_TRACE = 17;
+ }
+
+ // Which stage of the pipeline we are reporting from.
+ optional Event event = 1;
+
+ // UUID matching the one set inside the SystemInfo trace packet.
+ optional int64 trace_uuid_lsb = 2;
+ optional int64 trace_uuid_msb = 3;
+}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 9872e306eb9f..65f9678495ae 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2474,15 +2474,10 @@ public class Activity extends ContextThemeWrapper
if (mAutoFillResetNeeded) {
getAutofillManager().onInvisibleForAutofill();
- }
-
- if (isFinishing() && !mAutoFillResetNeeded && mIntent != null
- && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)) {
- // Activity was launched when user tapped a link in the Autofill Save UI - since
- // user launched another activity, the Save UI should not be restored when this
- // activity is finished.
- getAutofillManager().onPendingSaveUi(AutofillManager.PENDING_UI_OPERATION_CANCEL,
- mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN));
+ } else if (mIntent != null
+ && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)
+ && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY)) {
+ restoreAutofillSaveUi();
}
mEnterAnimationComplete = false;
}
@@ -2577,6 +2572,9 @@ public class Activity extends ContextThemeWrapper
* entirely drawn your UI and populated with all of the significant data. You
* can safely call this method any time after first launch as well, in which case
* it will simply be ignored.
+ * <p>If this method is called before the activity's window is <em>first</em> drawn
+ * and displayed as measured by the system, the reported time here will be shifted
+ * to the system measured time.
*/
public void reportFullyDrawn() {
if (mDoReportFullyDrawn) {
@@ -5530,6 +5528,21 @@ public class Activity extends ContextThemeWrapper
*/
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
+ if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)
+ && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY)) {
+ if (TextUtils.equals(getPackageName(),
+ intent.resolveActivity(getPackageManager()).getPackageName())) {
+ // Apply Autofill restore mechanism on the started activity by startActivity()
+ final IBinder token =
+ mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
+ // Remove restore ability from current activity
+ mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
+ mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY);
+ // Put restore token
+ intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
+ intent.putExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY, true);
+ }
+ }
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
@@ -6260,12 +6273,24 @@ public class Activity extends ContextThemeWrapper
// Activity was launched when user tapped a link in the Autofill Save UI - Save UI must
// be restored now.
if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)) {
- getAutofillManager().onPendingSaveUi(AutofillManager.PENDING_UI_OPERATION_RESTORE,
- mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN));
+ restoreAutofillSaveUi();
}
}
/**
+ * Restores Autofill Save UI
+ */
+ private void restoreAutofillSaveUi() {
+ final IBinder token =
+ mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
+ // Make only restore Autofill once
+ mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
+ mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY);
+ getAutofillManager().onPendingSaveUi(AutofillManager.PENDING_UI_OPERATION_RESTORE,
+ token);
+ }
+
+ /**
* Call this when your activity is done and should be closed. The
* ActivityResult is propagated back to whoever launched you via
* onActivityResult().
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 67728840ada8..f91453ea0811 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -1301,8 +1301,8 @@ public class ActivityOptions {
/**
* Set's whether the activity launched with this option should be a task overlay. That is the
- * activity will always be the top activity of the task. If {@param canResume} is true, then
- * the task will also not be moved to the front of the stack.
+ * activity will always be the top activity of the task.
+ * @param canResume {@code false} if the task will also not be moved to the front of the stack.
* @hide
*/
@TestApi
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index fbf1f59141a8..79ab67ac148c 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -16,94 +16,58 @@
package android.app;
-import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
-import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
-import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
-import static android.view.Display.INVALID_DISPLAY;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
-import android.app.ActivityManager.StackInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Insets;
import android.graphics.Matrix;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
-import android.hardware.display.DisplayManager;
-import android.hardware.display.VirtualDisplay;
-import android.hardware.input.InputManager;
-import android.os.RemoteException;
-import android.os.SystemClock;
import android.os.UserHandle;
import android.util.AttributeSet;
-import android.util.DisplayMetrics;
import android.util.Log;
+import android.view.IWindow;
import android.view.IWindowManager;
-import android.view.InputDevice;
-import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
-import android.view.SurfaceSession;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
-import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
-import android.view.inputmethod.InputMethodManager;
import dalvik.system.CloseGuard;
-import java.util.List;
-
/**
- * Activity container that allows launching activities into itself.
+ * Task container that allows launching activities into itself.
* <p>Activity launching into this container is restricted by the same rules that apply to launching
* on VirtualDisplays.
* @hide
*/
@TestApi
-public class ActivityView extends ViewGroup {
+public class ActivityView extends ViewGroup implements TaskEmbedder.Host {
- private static final String DISPLAY_NAME = "ActivityViewVirtualDisplay";
private static final String TAG = "ActivityView";
- private VirtualDisplay mVirtualDisplay;
- private final SurfaceView mSurfaceView;
-
- /**
- * This is the root surface for the VirtualDisplay. The VirtualDisplay child surfaces will be
- * re-parented to this surface. This will also be a child of the SurfaceView's SurfaceControl.
- */
- private SurfaceControl mRootSurfaceControl;
+ private TaskEmbedder mTaskEmbedder;
+ private final SurfaceView mSurfaceView;
private final SurfaceCallback mSurfaceCallback;
- private StateCallback mActivityViewCallback;
-
- private IActivityTaskManager mActivityTaskManager;
- // Temp container to store view coordinates in window.
- private final int[] mLocationInWindow = new int[2];
-
- // The latest tap exclude region that we've sent to WM.
- private final Region mTapExcludeRegion = new Region();
-
- private TaskStackListener mTaskStackListener;
private final CloseGuard mGuard = CloseGuard.get();
private boolean mOpened; // Protected by mGuard.
private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
- /** The ActivityView is only allowed to contain one task. */
- private final boolean mSingleTaskInstance;
-
- private Insets mForwardedInsets;
-
- private float mCornerRadius;
+ // For Host
+ private final Point mWindowPosition = new Point();
+ private final int[] mTmpArray = new int[2];
+ private final Matrix mScreenSurfaceMatrix = new Matrix();
+ private final Region mTapExcludeRegion = new Region();
public ActivityView(Context context) {
this(context, null /* attrs */);
@@ -120,9 +84,7 @@ public class ActivityView extends ViewGroup {
public ActivityView(
Context context, AttributeSet attrs, int defStyle, boolean singleTaskInstance) {
super(context, attrs, defStyle);
- mSingleTaskInstance = singleTaskInstance;
-
- mActivityTaskManager = ActivityTaskManager.getService();
+ mTaskEmbedder = new TaskEmbedder(getContext(), this, singleTaskInstance);
mSurfaceView = new SurfaceView(context);
// Since ActivityView#getAlpha has been overridden, we should use parent class's alpha
// as master to synchronize surface view's alpha value.
@@ -189,11 +151,11 @@ public class ActivityView extends ViewGroup {
* @see #startActivity(Intent)
*/
public void setCallback(StateCallback callback) {
- mActivityViewCallback = callback;
-
- if (mVirtualDisplay != null && mActivityViewCallback != null) {
- mActivityViewCallback.onActivityViewReady(this);
+ if (callback == null) {
+ mTaskEmbedder.setListener(null);
+ return;
}
+ mTaskEmbedder.setListener(new StateCallbackAdapter(callback));
}
/**
@@ -262,8 +224,7 @@ public class ActivityView extends ViewGroup {
* @see #startActivity(PendingIntent)
*/
public void startActivity(@NonNull Intent intent) {
- final ActivityOptions options = prepareActivityOptions();
- getContext().startActivity(intent, options.toBundle());
+ mTaskEmbedder.startActivity(intent);
}
/**
@@ -284,8 +245,7 @@ public class ActivityView extends ViewGroup {
* @see #startActivity(PendingIntent)
*/
public void startActivity(@NonNull Intent intent, UserHandle user) {
- final ActivityOptions options = prepareActivityOptions();
- getContext().startActivityAsUser(intent, options.toBundle(), user);
+ mTaskEmbedder.startActivity(intent, user);
}
/**
@@ -304,14 +264,7 @@ public class ActivityView extends ViewGroup {
* @see #startActivity(Intent)
*/
public void startActivity(@NonNull PendingIntent pendingIntent) {
- final ActivityOptions options = prepareActivityOptions();
- try {
- pendingIntent.send(null /* context */, 0 /* code */, null /* intent */,
- null /* onFinished */, null /* handler */, null /* requiredPermission */,
- options.toBundle());
- } catch (PendingIntent.CanceledException e) {
- throw new RuntimeException(e);
- }
+ mTaskEmbedder.startActivity(pendingIntent);
}
/**
@@ -333,28 +286,7 @@ public class ActivityView extends ViewGroup {
*/
public void startActivity(@NonNull PendingIntent pendingIntent, @Nullable Intent fillInIntent,
@NonNull ActivityOptions options) {
- options.setLaunchDisplayId(mVirtualDisplay.getDisplay().getDisplayId());
- try {
- pendingIntent.send(getContext(), 0 /* code */, fillInIntent,
- null /* onFinished */, null /* handler */, null /* requiredPermission */,
- options.toBundle());
- } catch (PendingIntent.CanceledException e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Check if container is ready to launch and create {@link ActivityOptions} to target the
- * virtual display.
- */
- private ActivityOptions prepareActivityOptions() {
- if (mVirtualDisplay == null) {
- throw new IllegalStateException(
- "Trying to start activity before ActivityView is ready.");
- }
- final ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchDisplayId(mVirtualDisplay.getDisplay().getDisplayId());
- return options;
+ mTaskEmbedder.startActivity(pendingIntent, fillInIntent, options);
}
/**
@@ -366,7 +298,7 @@ public class ActivityView extends ViewGroup {
* @see StateCallback
*/
public void release() {
- if (mVirtualDisplay == null) {
+ if (!mTaskEmbedder.isInitialized()) {
throw new IllegalStateException(
"Trying to release container that is not initialized.");
}
@@ -378,15 +310,7 @@ public class ActivityView extends ViewGroup {
* regions and avoid focus switches by touches on this view.
*/
public void onLocationChanged() {
- updateLocationAndTapExcludeRegion();
- }
-
- private void clearActivityViewGeometryForIme() {
- if (mVirtualDisplay == null) {
- return;
- }
- final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
- mContext.getSystemService(InputMethodManager.class).reportActivityView(displayId, null);
+ mTaskEmbedder.notifyBoundsChanged();
}
@Override
@@ -419,102 +343,31 @@ public class ActivityView extends ViewGroup {
public boolean gatherTransparentRegion(Region region) {
// The tap exclude region may be affected by any view on top of it, so we detect the
// possible change by monitoring this function.
- updateLocationAndTapExcludeRegion();
+ mTaskEmbedder.notifyBoundsChanged();
return super.gatherTransparentRegion(region);
}
- /**
- * Sends current location in window and tap exclude region to WM for this view.
- */
- private void updateLocationAndTapExcludeRegion() {
- if (mVirtualDisplay == null || !isAttachedToWindow()) {
- return;
- }
- try {
- int x = mLocationInWindow[0];
- int y = mLocationInWindow[1];
- getLocationInWindow(mLocationInWindow);
- if (x != mLocationInWindow[0] || y != mLocationInWindow[1]) {
- x = mLocationInWindow[0];
- y = mLocationInWindow[1];
- final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
- WindowManagerGlobal.getWindowSession().updateDisplayContentLocation(
- getWindow(), x, y, displayId);
-
- // Also report this geometry information to InputMethodManagerService.
- // TODO(b/115693908): Unify this logic into the above WMS-based one.
- // TODO(b/138175283): Address the location update when the host of this view is
- // moving.
- final Matrix matrix = new Matrix();
- final int[] locationOnScreen = new int[2];
- getLocationOnScreen(locationOnScreen);
- final int dx = locationOnScreen[0];
- final int dy = locationOnScreen[1];
- matrix.set(getMatrix());
- matrix.postTranslate(dx, dy);
- mContext.getSystemService(InputMethodManager.class)
- .reportActivityView(displayId, matrix);
- }
- updateTapExcludeRegion(x, y);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
- }
-
- /** Computes and sends current tap exclude region to WM for this view. */
- private void updateTapExcludeRegion(int x, int y) throws RemoteException {
- if (!canReceivePointerEvents()) {
- cleanTapExcludeRegion();
- return;
- }
- mTapExcludeRegion.set(x, y, x + getWidth(), y + getHeight());
-
- // There might be views on top of us. We need to subtract those areas from the tap
- // exclude region.
- final ViewParent parent = getParent();
- if (parent != null) {
- parent.subtractObscuredTouchableRegion(mTapExcludeRegion, this);
- }
-
- WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
- mTapExcludeRegion);
- }
-
private class SurfaceCallback implements SurfaceHolder.Callback {
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
- if (mVirtualDisplay == null) {
- initVirtualDisplay(new SurfaceSession());
- if (mVirtualDisplay != null && mActivityViewCallback != null) {
- mActivityViewCallback.onActivityViewReady(ActivityView.this);
- }
+ if (!mTaskEmbedder.isInitialized()) {
+ initTaskEmbedder(mSurfaceView.getSurfaceControl());
} else {
- mTmpTransaction.reparent(mRootSurfaceControl,
+ mTmpTransaction.reparent(mTaskEmbedder.getSurfaceControl(),
mSurfaceView.getSurfaceControl()).apply();
}
-
- if (mVirtualDisplay != null) {
- mVirtualDisplay.setDisplayState(true);
- }
-
- updateLocationAndTapExcludeRegion();
+ mTaskEmbedder.start();
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
- if (mVirtualDisplay != null) {
- mVirtualDisplay.resize(width, height, getBaseDisplayDensity());
- }
- updateLocationAndTapExcludeRegion();
+ mTaskEmbedder.resizeTask(width, height);
+ mTaskEmbedder.notifyBoundsChanged();
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
- if (mVirtualDisplay != null) {
- mVirtualDisplay.setDisplayState(false);
- }
- clearActivityViewGeometryForIme();
- cleanTapExcludeRegion();
+ mTaskEmbedder.stop();
}
}
@@ -528,10 +381,7 @@ public class ActivityView extends ViewGroup {
* @return the display id of the virtual display.
*/
public int getVirtualDisplayId() {
- if (mVirtualDisplay != null) {
- return mVirtualDisplay.getDisplay().getDisplayId();
- }
- return INVALID_DISPLAY;
+ return mTaskEmbedder.getDisplayId();
}
/**
@@ -539,135 +389,36 @@ public class ActivityView extends ViewGroup {
* virtual display.
*/
public void performBackPress() {
- if (mVirtualDisplay == null) {
- return;
- }
- final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
- final InputManager im = InputManager.getInstance();
- im.injectInputEvent(createKeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK, displayId),
- InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
- im.injectInputEvent(createKeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK, displayId),
- InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
- }
-
- private static KeyEvent createKeyEvent(int action, int code, int displayId) {
- long when = SystemClock.uptimeMillis();
- final KeyEvent ev = new KeyEvent(when, when, action, code, 0 /* repeat */,
- 0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
- KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
- InputDevice.SOURCE_KEYBOARD);
- ev.setDisplayId(displayId);
- return ev;
- }
-
- private void initVirtualDisplay(SurfaceSession surfaceSession) {
- if (mVirtualDisplay != null) {
- throw new IllegalStateException("Trying to initialize for the second time.");
- }
-
- final int width = mSurfaceView.getWidth();
- final int height = mSurfaceView.getHeight();
- final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
+ mTaskEmbedder.performBackPress();
+ }
- mVirtualDisplay = displayManager.createVirtualDisplay(
- DISPLAY_NAME + "@" + System.identityHashCode(this), width, height,
- getBaseDisplayDensity(), null,
- VIRTUAL_DISPLAY_FLAG_PUBLIC | VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
- | VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL);
- if (mVirtualDisplay == null) {
+ /**
+ * Initializes the task embedder.
+ *
+ * @param parent control for the surface to parent to
+ * @return true if the task embedder has been initialized
+ */
+ private boolean initTaskEmbedder(SurfaceControl parent) {
+ if (!mTaskEmbedder.initialize(parent)) {
Log.e(TAG, "Failed to initialize ActivityView");
- return;
- }
-
- final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
- final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
-
- mRootSurfaceControl = new SurfaceControl.Builder(surfaceSession)
- .setContainerLayer()
- .setParent(mSurfaceView.getSurfaceControl())
- .setName(DISPLAY_NAME)
- .build();
-
- try {
- // TODO: Find a way to consolidate these calls to the server.
- WindowManagerGlobal.getWindowSession().reparentDisplayContent(
- getWindow(), mRootSurfaceControl, displayId);
- wm.dontOverrideDisplayInfo(displayId);
- if (mSingleTaskInstance) {
- mActivityTaskManager.setDisplayToSingleTaskInstance(displayId);
- }
- wm.setForwardedInsets(displayId, mForwardedInsets);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
-
- mTmpTransaction.show(mRootSurfaceControl).apply();
- mTaskStackListener = new TaskStackListenerImpl();
- try {
- mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to register task stack listener", e);
+ return false;
}
+ mTmpTransaction.show(mTaskEmbedder.getSurfaceControl()).apply();
+ return true;
}
private void performRelease() {
if (!mOpened) {
return;
}
-
mSurfaceView.getHolder().removeCallback(mSurfaceCallback);
-
- cleanTapExcludeRegion();
-
- if (mTaskStackListener != null) {
- try {
- mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to unregister task stack listener", e);
- }
- mTaskStackListener = null;
- }
-
- final boolean displayReleased;
- if (mVirtualDisplay != null) {
- mVirtualDisplay.release();
- mVirtualDisplay = null;
- displayReleased = true;
- } else {
- displayReleased = false;
- }
-
- if (displayReleased && mActivityViewCallback != null) {
- mActivityViewCallback.onActivityViewDestroyed(this);
- }
+ mTaskEmbedder.setListener(null);
+ mTaskEmbedder.release();
mGuard.close();
mOpened = false;
}
- /** Report to server that tap exclude region on hosting display should be cleared. */
- private void cleanTapExcludeRegion() {
- if (!isAttachedToWindow() || mTapExcludeRegion.isEmpty()) {
- return;
- }
- // Update tap exclude region with a null region to clean the state on server.
- try {
- WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
- null /* region */);
- mTapExcludeRegion.setEmpty();
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
- }
-
- /** Get density of the hosting display. */
- private int getBaseDisplayDensity() {
- final WindowManager wm = mContext.getSystemService(WindowManager.class);
- final DisplayMetrics metrics = new DisplayMetrics();
- wm.getDefaultDisplay().getMetrics(metrics);
- return metrics.densityDpi;
- }
-
@Override
protected void finalize() throws Throwable {
try {
@@ -686,108 +437,100 @@ public class ActivityView extends ViewGroup {
* @see IWindowManager#setForwardedInsets
*/
public void setForwardedInsets(Insets insets) {
- mForwardedInsets = insets;
- if (mVirtualDisplay == null) {
- return;
+ mTaskEmbedder.setForwardedInsets(insets);
+ }
+
+ // Host
+
+ /** @hide */
+ @Override
+ public void onTaskBackgroundColorChanged(TaskEmbedder ts, int bgColor) {
+ if (mSurfaceView != null) {
+ mSurfaceView.setResizeBackgroundColor(bgColor);
}
- try {
- final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
- wm.setForwardedInsets(mVirtualDisplay.getDisplay().getDisplayId(), mForwardedInsets);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
+ }
+
+ /** @hide */
+ @Override
+ public Region getTapExcludeRegion() {
+ if (isAttachedToWindow() && canReceivePointerEvents()) {
+ Point windowPos = getPositionInWindow();
+ mTapExcludeRegion.set(
+ windowPos.x,
+ windowPos.y,
+ windowPos.x + getWidth(),
+ windowPos.y + getHeight());
+ // There might be views on top of us. We need to subtract those areas from the tap
+ // exclude region.
+ final ViewParent parent = getParent();
+ if (parent != null) {
+ parent.subtractObscuredTouchableRegion(mTapExcludeRegion, this);
+ }
+ } else {
+ mTapExcludeRegion.setEmpty();
}
+ return mTapExcludeRegion;
}
- /**
- * A task change listener that detects background color change of the topmost stack on our
- * virtual display and updates the background of the surface view. This background will be shown
- * when surface view is resized, but the app hasn't drawn its content in new size yet.
- * It also calls StateCallback.onTaskMovedToFront to notify interested parties that the stack
- * associated with the {@link ActivityView} has had a Task moved to the front. This is useful
- * when needing to also bring the host Activity to the foreground at the same time.
- */
- private class TaskStackListenerImpl extends TaskStackListener {
+ /** @hide */
+ @Override
+ public Matrix getScreenToTaskMatrix() {
+ getLocationOnScreen(mTmpArray);
+ mScreenSurfaceMatrix.set(getMatrix());
+ mScreenSurfaceMatrix.postTranslate(mTmpArray[0], mTmpArray[1]);
+ return mScreenSurfaceMatrix;
+ }
- @Override
- public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo)
- throws RemoteException {
- if (mVirtualDisplay == null
- || taskInfo.displayId != mVirtualDisplay.getDisplay().getDisplayId()) {
- return;
- }
+ /** @hide */
+ @Override
+ public Point getPositionInWindow() {
+ getLocationInWindow(mTmpArray);
+ mWindowPosition.set(mTmpArray[0], mTmpArray[1]);
+ return mWindowPosition;
+ }
- StackInfo stackInfo = getTopMostStackInfo();
- if (stackInfo == null) {
- return;
- }
- // Found the topmost stack on target display. Now check if the topmost task's
- // description changed.
- if (taskInfo.taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
- mSurfaceView.setResizeBackgroundColor(
- taskInfo.taskDescription.getBackgroundColor());
- }
+ /** @hide */
+ @Override
+ public IWindow getWindow() {
+ return super.getWindow();
+ }
+
+ /** @hide */
+ @Override
+ public boolean canReceivePointerEvents() {
+ return super.canReceivePointerEvents();
+ }
+
+ private final class StateCallbackAdapter implements TaskEmbedder.Listener {
+ private final StateCallback mCallback;
+
+ private StateCallbackAdapter(ActivityView.StateCallback cb) {
+ mCallback = cb;
}
@Override
- public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo)
- throws RemoteException {
- if (mActivityViewCallback == null || mVirtualDisplay == null
- || taskInfo.displayId != mVirtualDisplay.getDisplay().getDisplayId()) {
- return;
- }
-
- StackInfo stackInfo = getTopMostStackInfo();
- // if StackInfo was null or unrelated to the "move to front" then there's no use
- // notifying the callback
- if (stackInfo != null
- && taskInfo.taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
- mActivityViewCallback.onTaskMovedToFront(taskInfo.taskId);
- }
+ public void onInitialized() {
+ mCallback.onActivityViewReady(ActivityView.this);
}
@Override
- public void onTaskCreated(int taskId, ComponentName componentName) throws RemoteException {
- if (mActivityViewCallback == null || mVirtualDisplay == null) {
- return;
- }
+ public void onReleased() {
+ mCallback.onActivityViewDestroyed(ActivityView.this);
+ }
- StackInfo stackInfo = getTopMostStackInfo();
- // if StackInfo was null or unrelated to the task creation then there's no use
- // notifying the callback
- if (stackInfo != null
- && taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
- mActivityViewCallback.onTaskCreated(taskId, componentName);
- }
+ @Override
+ public void onTaskCreated(int taskId, ComponentName name) {
+ mCallback.onTaskCreated(taskId, name);
}
@Override
- public void onTaskRemovalStarted(ActivityManager.RunningTaskInfo taskInfo)
- throws RemoteException {
- if (mActivityViewCallback == null || mVirtualDisplay == null
- || taskInfo.displayId != mVirtualDisplay.getDisplay().getDisplayId()) {
- return;
- }
- mActivityViewCallback.onTaskRemovalStarted(taskInfo.taskId);
+ public void onTaskMovedToFront(int taskId) {
+ mCallback.onTaskMovedToFront(taskId);
}
- private StackInfo getTopMostStackInfo() throws RemoteException {
- // Find the topmost task on our virtual display - it will define the background
- // color of the surface view during resizing.
- final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
- final List<StackInfo> stackInfoList = mActivityTaskManager.getAllStackInfos();
-
- // Iterate through stacks from top to bottom.
- final int stackCount = stackInfoList.size();
- for (int i = 0; i < stackCount; i++) {
- final StackInfo stackInfo = stackInfoList.get(i);
- // Only look for stacks on our virtual display.
- if (stackInfo.displayId != displayId) {
- continue;
- }
- // Found the topmost stack on target display.
- return stackInfo;
- }
- return null;
+ @Override
+ public void onTaskRemovalStarted(int taskId) {
+ mCallback.onTaskRemovalStarted(taskId);
}
}
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index efb9f6bb88f1..47118a81632e 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -17,7 +17,6 @@
package android.app;
import static android.annotation.Dimension.DP;
-import static android.graphics.drawable.Icon.TYPE_BITMAP;
import static com.android.internal.util.ContrastColorUtil.satisfiesTextContrast;
@@ -8741,26 +8740,20 @@ public class Notification implements Parcelable
* If your app produces multiple bubbles, the image should be unique for each of them.
* </p>
*
- * <p>The shape of a bubble icon is adaptive and can match the device theme.
+ * <p>The shape of a bubble icon is adaptive and will match the device theme.
*
- * If your icon is bitmap-based, you should create it using
- * {@link Icon#createWithAdaptiveBitmap(Bitmap)}, otherwise this method will throw.
- *
- * If your icon is not bitmap-based, you should expect that the icon will be tinted.
+ * Ideally your icon should be constructed via
+ * {@link Icon#createWithAdaptiveBitmap(Bitmap)}, otherwise, the icon will be shrunk
+ * and placed on an adaptive shape.
* </p>
*
- * @throws IllegalArgumentException if icon is null or a non-adaptive bitmap
+ * @throws IllegalArgumentException if icon is null.
*/
@NonNull
public BubbleMetadata.Builder setIcon(@NonNull Icon icon) {
if (icon == null) {
throw new IllegalArgumentException("Bubbles require non-null icon");
}
- if (icon.getType() == TYPE_BITMAP) {
- throw new IllegalArgumentException("When using bitmap based icons, Bubbles "
- + "require TYPE_ADAPTIVE_BITMAP, please use"
- + " Icon#createWithAdaptiveBitmap instead");
- }
mIcon = icon;
return this;
}
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 3ad88829b812..06b95067c2e8 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -1274,7 +1274,12 @@ public final class PendingIntent implements Parcelable {
return b != null ? new PendingIntent(b, in.getClassCookie(PendingIntent.class)) : null;
}
- /*package*/ PendingIntent(IIntentSender target) {
+ /**
+ * Creates a PendingIntent with the given target.
+ * @param target the backing IIntentSender
+ * @hide
+ */
+ public PendingIntent(IIntentSender target) {
mTarget = target;
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 629c2bb19a7c..36d899ea611f 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -170,6 +170,7 @@ import android.telephony.TelephonyManager;
import android.telephony.TelephonyRegistryManager;
import android.telephony.euicc.EuiccCardManager;
import android.telephony.euicc.EuiccManager;
+import android.telephony.ims.ImsManager;
import android.telephony.ims.RcsMessageManager;
import android.util.ArrayMap;
import android.util.Log;
@@ -631,6 +632,14 @@ public final class SystemServiceRegistry {
}
});
+ registerService(Context.TELEPHONY_IMS_SERVICE, ImsManager.class,
+ new CachedServiceFetcher<ImsManager>() {
+ @Override
+ public ImsManager createService(ContextImpl ctx) {
+ return new ImsManager(ctx.getOuterContext());
+ }
+ });
+
registerService(Context.CARRIER_CONFIG_SERVICE, CarrierConfigManager.class,
new CachedServiceFetcher<CarrierConfigManager>() {
@Override
diff --git a/core/java/android/app/TaskEmbedder.java b/core/java/android/app/TaskEmbedder.java
new file mode 100644
index 000000000000..a1389bdbaf7b
--- /dev/null
+++ b/core/java/android/app/TaskEmbedder.java
@@ -0,0 +1,674 @@
+/*
+ * 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.app;
+
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Insets;
+import android.graphics.Matrix;
+import android.graphics.Point;
+import android.graphics.Region;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.VirtualDisplay;
+import android.hardware.input.InputManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Display;
+import android.view.IWindow;
+import android.view.IWindowManager;
+import android.view.IWindowSession;
+import android.view.InputDevice;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.SurfaceControl;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+import android.view.inputmethod.InputMethodManager;
+
+import dalvik.system.CloseGuard;
+
+import java.util.List;
+
+/**
+ * A component which handles embedded display of tasks within another window. The embedded task can
+ * be presented using the SurfaceControl provided from {@link #getSurfaceControl()}.
+ *
+ * @hide
+ */
+public class TaskEmbedder {
+ private static final String TAG = "TaskEmbedder";
+ private static final String DISPLAY_NAME = "TaskVirtualDisplay";
+
+ /**
+ * A component which will host the task.
+ */
+ public interface Host {
+ /** @return the screen area where touches should be dispatched to the embedded Task */
+ Region getTapExcludeRegion();
+
+ /** @return a matrix which transforms from screen-space to the embedded task surface */
+ Matrix getScreenToTaskMatrix();
+
+ /** @return the window containing the parent surface, if attached and available */
+ @Nullable IWindow getWindow();
+
+ /** @return the x/y offset from the origin of the window to the surface */
+ Point getPositionInWindow();
+
+ /** @return whether this surface is able to receive pointer events */
+ boolean canReceivePointerEvents();
+
+ /** @return the width of the container for the embedded task */
+ int getWidth();
+
+ /** @return the height of the container for the embedded task */
+ int getHeight();
+
+ /**
+ * Called to inform the host of the task's background color. This can be used to
+ * fill unpainted areas if necessary.
+ */
+ void onTaskBackgroundColorChanged(TaskEmbedder ts, int bgColor);
+ }
+
+ /**
+ * Describes changes to the state of the TaskEmbedder as well the tasks within.
+ */
+ public interface Listener {
+ /** Called when the container is ready for launching activities. */
+ default void onInitialized() {}
+
+ /** Called when the container can no longer launch activities. */
+ default void onReleased() {}
+
+ /** Called when a task is created inside the container. */
+ default void onTaskCreated(int taskId, ComponentName name) {}
+
+ /** Called when a task is moved to the front of the stack inside the container. */
+ default void onTaskMovedToFront(int taskId) {}
+
+ /** Called when a task is about to be removed from the stack inside the container. */
+ default void onTaskRemovalStarted(int taskId) {}
+ }
+
+ private IActivityTaskManager mActivityTaskManager = ActivityTaskManager.getService();
+
+ private final Context mContext;
+ private TaskEmbedder.Host mHost;
+ private int mDisplayDensityDpi;
+ private final boolean mSingleTaskInstance;
+ private SurfaceControl.Transaction mTransaction;
+ private SurfaceControl mSurfaceControl;
+ private VirtualDisplay mVirtualDisplay;
+ private Insets mForwardedInsets;
+ private TaskStackListener mTaskStackListener;
+ private Listener mListener;
+ private boolean mOpened; // Protected by mGuard.
+
+ private final CloseGuard mGuard = CloseGuard.get();
+
+
+ /**
+ * Constructs a new TaskEmbedder.
+ *
+ * @param context the context
+ * @param host the host for this embedded task
+ * @param singleTaskInstance whether to apply a single-task constraint to this container
+ */
+ public TaskEmbedder(Context context, TaskEmbedder.Host host, boolean singleTaskInstance) {
+ mContext = context;
+ mHost = host;
+ mSingleTaskInstance = singleTaskInstance;
+ }
+
+ /**
+ * Whether this container has been initialized.
+ *
+ * @return true if initialized
+ */
+ public boolean isInitialized() {
+ return mVirtualDisplay != null;
+ }
+
+ /**
+ * Initialize this container.
+ *
+ * @param parent the surface control for the parent surface
+ * @return true if initialized successfully
+ */
+ public boolean initialize(SurfaceControl parent) {
+ if (mVirtualDisplay != null) {
+ throw new IllegalStateException("Trying to initialize for the second time.");
+ }
+
+ mTransaction = new SurfaceControl.Transaction();
+
+ final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
+ mDisplayDensityDpi = getBaseDisplayDensity();
+
+ mVirtualDisplay = displayManager.createVirtualDisplay(
+ DISPLAY_NAME + "@" + System.identityHashCode(this), mHost.getWidth(),
+ mHost.getHeight(), mDisplayDensityDpi, null,
+ VIRTUAL_DISPLAY_FLAG_PUBLIC | VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
+ | VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL);
+
+ if (mVirtualDisplay == null) {
+ Log.e(TAG, "Failed to initialize TaskEmbedder");
+ return false;
+ }
+
+ // Create a container surface to which the ActivityDisplay will be reparented
+ final String name = "TaskEmbedder - " + Integer.toHexString(System.identityHashCode(this));
+ mSurfaceControl = new SurfaceControl.Builder()
+ .setContainerLayer()
+ .setParent(parent)
+ .setName(name)
+ .build();
+
+ final int displayId = getDisplayId();
+
+ final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+ try {
+ // TODO: Find a way to consolidate these calls to the server.
+ WindowManagerGlobal.getWindowSession().reparentDisplayContent(
+ mHost.getWindow(), mSurfaceControl, displayId);
+ wm.dontOverrideDisplayInfo(displayId);
+ if (mSingleTaskInstance) {
+ mContext.getSystemService(ActivityTaskManager.class)
+ .setDisplayToSingleTaskInstance(displayId);
+ }
+ setForwardedInsets(mForwardedInsets);
+ if (mHost.getWindow() != null) {
+ updateLocationAndTapExcludeRegion();
+ }
+ mTaskStackListener = new TaskStackListenerImpl();
+ try {
+ mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to register task stack listener", e);
+ }
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ if (mListener != null && mVirtualDisplay != null) {
+ mListener.onInitialized();
+ }
+ mOpened = true;
+ mGuard.open("release");
+ return true;
+ }
+
+ /**
+ * Returns the surface control for the task surface. This should be parented to a screen
+ * surface for display/embedding purposes.
+ *
+ * @return the surface control for the task
+ */
+ public SurfaceControl getSurfaceControl() {
+ return mSurfaceControl;
+ }
+
+ /**
+ * Set forwarded insets on the virtual display.
+ *
+ * @see IWindowManager#setForwardedInsets
+ */
+ public void setForwardedInsets(Insets insets) {
+ mForwardedInsets = insets;
+ if (mVirtualDisplay == null) {
+ return;
+ }
+ try {
+ final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+ wm.setForwardedInsets(getDisplayId(), mForwardedInsets);
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+
+ /** An opaque unique identifier for this task surface among others being managed by the app. */
+ public int getId() {
+ return getDisplayId();
+ }
+
+ int getDisplayId() {
+ if (mVirtualDisplay != null) {
+ return mVirtualDisplay.getDisplay().getDisplayId();
+ }
+ return Display.INVALID_DISPLAY;
+ }
+
+ /**
+ * Set the callback to be notified about state changes.
+ * <p>This class must finish initializing before {@link #startActivity(Intent)} can be called.
+ * <p>Note: If the instance was ready prior to this call being made, then
+ * {@link Listener#onInitialized()} will be called from within this method call.
+ *
+ * @param listener The listener to report events to.
+ *
+ * @see ActivityView.StateCallback
+ * @see #startActivity(Intent)
+ */
+ void setListener(TaskEmbedder.Listener listener) {
+ mListener = listener;
+ if (mListener != null && isInitialized()) {
+ mListener.onInitialized();
+ }
+ }
+
+ /**
+ * Launch a new activity into this container.
+ *
+ * @param intent Intent used to launch an activity
+ *
+ * @see #startActivity(PendingIntent)
+ */
+ public void startActivity(@NonNull Intent intent) {
+ final ActivityOptions options = prepareActivityOptions();
+ mContext.startActivity(intent, options.toBundle());
+ }
+
+ /**
+ * Launch a new activity into this container.
+ *
+ * @param intent Intent used to launch an activity
+ * @param user The UserHandle of the user to start this activity for
+ *
+ * @see #startActivity(PendingIntent)
+ */
+ public void startActivity(@NonNull Intent intent, UserHandle user) {
+ final ActivityOptions options = prepareActivityOptions();
+ mContext.startActivityAsUser(intent, options.toBundle(), user);
+ }
+
+ /**
+ * Launch a new activity into this container.
+ *
+ * @param pendingIntent Intent used to launch an activity
+ *
+ * @see #startActivity(Intent)
+ */
+ public void startActivity(@NonNull PendingIntent pendingIntent) {
+ final ActivityOptions options = prepareActivityOptions();
+ try {
+ pendingIntent.send(null /* context */, 0 /* code */, null /* intent */,
+ null /* onFinished */, null /* handler */, null /* requiredPermission */,
+ options.toBundle());
+ } catch (PendingIntent.CanceledException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Launch a new activity into this container.
+ *
+ * @param pendingIntent Intent used to launch an activity
+ * @param fillInIntent Additional Intent data, see {@link Intent#fillIn Intent.fillIn()}
+ * @param options options for the activity
+ *
+ * @see #startActivity(Intent)
+ */
+ public void startActivity(@NonNull PendingIntent pendingIntent, @Nullable Intent fillInIntent,
+ @NonNull ActivityOptions options) {
+
+ options.setLaunchDisplayId(mVirtualDisplay.getDisplay().getDisplayId());
+ try {
+ pendingIntent.send(mContext, 0 /* code */, fillInIntent,
+ null /* onFinished */, null /* handler */, null /* requiredPermission */,
+ options.toBundle());
+ } catch (PendingIntent.CanceledException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Check if container is ready to launch and create {@link ActivityOptions} to target the
+ * virtual display.
+ */
+ private ActivityOptions prepareActivityOptions() {
+ if (mVirtualDisplay == null) {
+ throw new IllegalStateException(
+ "Trying to start activity before ActivityView is ready.");
+ }
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchDisplayId(getDisplayId());
+ return options;
+ }
+
+ /**
+ * Stops presentation of tasks in this container.
+ */
+ public void stop() {
+ if (mVirtualDisplay != null) {
+ mVirtualDisplay.setDisplayState(false);
+ clearActivityViewGeometryForIme();
+ clearTapExcludeRegion();
+ }
+ }
+
+ /**
+ * Starts presentation of tasks in this container.
+ */
+ public void start() {
+ if (mVirtualDisplay != null) {
+ mVirtualDisplay.setDisplayState(true);
+ updateLocationAndTapExcludeRegion();
+ }
+ }
+
+ /**
+ * This should be called whenever the position or size of the surface changes
+ * or if touchable areas above the surface are added or removed.
+ */
+ public void notifyBoundsChanged() {
+ updateLocationAndTapExcludeRegion();
+ }
+
+ /**
+ * Updates position and bounds information needed by WM and IME to manage window
+ * focus and touch events properly.
+ * <p>
+ * This should be called whenever the position or size of the surface changes
+ * or if touchable areas above the surface are added or removed.
+ */
+ private void updateLocationAndTapExcludeRegion() {
+ if (mVirtualDisplay == null || mHost.getWindow() == null) {
+ return;
+ }
+ reportLocation(mHost.getScreenToTaskMatrix(), mHost.getPositionInWindow());
+ applyTapExcludeRegion(mHost.getWindow(), hashCode(), mHost.getTapExcludeRegion());
+ }
+
+ /**
+ * Call to update the position and transform matrix for the embedded surface.
+ * <p>
+ * This should not normally be called directly, but through
+ * {@link #updateLocationAndTapExcludeRegion()}. This method
+ * is provided as an optimization when managing multiple TaskSurfaces within a view.
+ *
+ * @param screenToViewMatrix the matrix/transform from screen space to view space
+ * @param positionInWindow the window-relative position of the surface
+ *
+ * @see InputMethodManager#reportActivityView(int, Matrix)
+ */
+ private void reportLocation(Matrix screenToViewMatrix, Point positionInWindow) {
+ try {
+ final int displayId = getDisplayId();
+ mContext.getSystemService(InputMethodManager.class)
+ .reportActivityView(displayId, screenToViewMatrix);
+ IWindowSession session = WindowManagerGlobal.getWindowSession();
+ session.updateDisplayContentLocation(mHost.getWindow(), positionInWindow.x,
+ positionInWindow.y, displayId);
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Call to update the tap exclude region for the window.
+ * <p>
+ * This should not normally be called directly, but through
+ * {@link #updateLocationAndTapExcludeRegion()}. This method
+ * is provided as an optimization when managing multiple TaskSurfaces within a view.
+ *
+ * @see IWindowSession#updateTapExcludeRegion(IWindow, int, Region)
+ */
+ private void applyTapExcludeRegion(IWindow window, int regionId,
+ @Nullable Region tapExcludeRegion) {
+ try {
+ IWindowSession session = WindowManagerGlobal.getWindowSession();
+ session.updateTapExcludeRegion(window, regionId, tapExcludeRegion);
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * @see InputMethodManager#reportActivityView(int, Matrix)
+ */
+ private void clearActivityViewGeometryForIme() {
+ final int displayId = getDisplayId();
+ mContext.getSystemService(InputMethodManager.class).reportActivityView(displayId, null);
+ }
+
+ /**
+ * Removes the tap exclude region set by {@link #updateLocationAndTapExcludeRegion()}.
+ */
+ private void clearTapExcludeRegion() {
+ if (mHost.getWindow() == null) {
+ Log.w(TAG, "clearTapExcludeRegion: not attached to window!");
+ return;
+ }
+ applyTapExcludeRegion(mHost.getWindow(), hashCode(), null);
+ }
+
+ /**
+ * Called to update the dimensions whenever the host size changes.
+ *
+ * @param width the new width of the surface
+ * @param height the new height of the surface
+ */
+ public void resizeTask(int width, int height) {
+ mDisplayDensityDpi = getBaseDisplayDensity();
+ if (mVirtualDisplay != null) {
+ mVirtualDisplay.resize(width, height, mDisplayDensityDpi);
+ }
+ }
+
+ /**
+ * Injects a pair of down/up key events with keycode {@link KeyEvent#KEYCODE_BACK} to the
+ * virtual display.
+ */
+ public void performBackPress() {
+ if (mVirtualDisplay == null) {
+ return;
+ }
+ final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
+ final InputManager im = InputManager.getInstance();
+ im.injectInputEvent(createKeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK, displayId),
+ InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+ im.injectInputEvent(createKeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK, displayId),
+ InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+ }
+
+ private static KeyEvent createKeyEvent(int action, int code, int displayId) {
+ long when = SystemClock.uptimeMillis();
+ final KeyEvent ev = new KeyEvent(when, when, action, code, 0 /* repeat */,
+ 0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
+ KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
+ InputDevice.SOURCE_KEYBOARD);
+ ev.setDisplayId(displayId);
+ return ev;
+ }
+
+ /**
+ * Releases the resources for this TaskEmbedder. Tasks will no longer be launchable
+ * within this container.
+ *
+ * <p>Note: Calling this method is allowed after {@link Listener#onInitialized()} callback is
+ * triggered and before {@link Listener#onReleased()}.
+ */
+ public void release() {
+ if (mVirtualDisplay == null) {
+ throw new IllegalStateException(
+ "Trying to release container that is not initialized.");
+ }
+ performRelease();
+ }
+
+ private boolean performRelease() {
+ if (!mOpened) {
+ return false;
+ }
+ mTransaction.reparent(mSurfaceControl, null).apply();
+ mSurfaceControl.release();
+
+ // Clear activity view geometry for IME on this display
+ clearActivityViewGeometryForIme();
+
+ // Clear tap-exclude region (if any) for this window.
+ clearTapExcludeRegion();
+
+ if (mTaskStackListener != null) {
+ try {
+ mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to unregister task stack listener", e);
+ }
+ mTaskStackListener = null;
+ }
+
+ boolean reportReleased = false;
+ if (mVirtualDisplay != null) {
+ mVirtualDisplay.release();
+ mVirtualDisplay = null;
+ reportReleased = true;
+
+ }
+
+ if (mListener != null && reportReleased) {
+ mListener.onReleased();
+ }
+ mOpened = false;
+ mGuard.close();
+ return true;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ if (mGuard != null) {
+ mGuard.warnIfOpen();
+ performRelease();
+ }
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /** Get density of the hosting display. */
+ private int getBaseDisplayDensity() {
+ final WindowManager wm = mContext.getSystemService(WindowManager.class);
+ final DisplayMetrics metrics = new DisplayMetrics();
+ wm.getDefaultDisplay().getMetrics(metrics);
+ return metrics.densityDpi;
+ }
+
+ /**
+ * A task change listener that detects background color change of the topmost stack on our
+ * virtual display and updates the background of the surface view. This background will be shown
+ * when surface view is resized, but the app hasn't drawn its content in new size yet.
+ * It also calls StateCallback.onTaskMovedToFront to notify interested parties that the stack
+ * associated with the {@link ActivityView} has had a Task moved to the front. This is useful
+ * when needing to also bring the host Activity to the foreground at the same time.
+ */
+ private class TaskStackListenerImpl extends TaskStackListener {
+
+ @Override
+ public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo)
+ throws RemoteException {
+ if (!isInitialized()
+ || taskInfo.displayId != getDisplayId()) {
+ return;
+ }
+
+ ActivityManager.StackInfo stackInfo = getTopMostStackInfo();
+ if (stackInfo == null) {
+ return;
+ }
+ // Found the topmost stack on target display. Now check if the topmost task's
+ // description changed.
+ if (taskInfo.taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
+ mHost.onTaskBackgroundColorChanged(TaskEmbedder.this,
+ taskInfo.taskDescription.getBackgroundColor());
+ }
+ }
+
+ @Override
+ public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo)
+ throws RemoteException {
+ if (!isInitialized() || mListener == null
+ || taskInfo.displayId != getDisplayId()) {
+ return;
+ }
+
+ ActivityManager.StackInfo stackInfo = getTopMostStackInfo();
+ // if StackInfo was null or unrelated to the "move to front" then there's no use
+ // notifying the callback
+ if (stackInfo != null
+ && taskInfo.taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
+ mListener.onTaskMovedToFront(taskInfo.taskId);
+ }
+ }
+
+ @Override
+ public void onTaskCreated(int taskId, ComponentName componentName) throws RemoteException {
+ if (mListener == null || !isInitialized()) {
+ return;
+ }
+
+ ActivityManager.StackInfo stackInfo = getTopMostStackInfo();
+ // if StackInfo was null or unrelated to the task creation then there's no use
+ // notifying the callback
+ if (stackInfo != null
+ && taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
+ mListener.onTaskCreated(taskId, componentName);
+ }
+ }
+
+ @Override
+ public void onTaskRemovalStarted(ActivityManager.RunningTaskInfo taskInfo)
+ throws RemoteException {
+ if (mListener == null || !isInitialized()
+ || taskInfo.displayId != getDisplayId()) {
+ return;
+ }
+ mListener.onTaskRemovalStarted(taskInfo.taskId);
+ }
+
+ private ActivityManager.StackInfo getTopMostStackInfo() throws RemoteException {
+ // Find the topmost task on our virtual display - it will define the background
+ // color of the surface view during resizing.
+ final int displayId = getDisplayId();
+ final List<ActivityManager.StackInfo> stackInfoList =
+ mActivityTaskManager.getAllStackInfos();
+
+ // Iterate through stacks from top to bottom.
+ final int stackCount = stackInfoList.size();
+ for (int i = 0; i < stackCount; i++) {
+ final ActivityManager.StackInfo stackInfo = stackInfoList.get(i);
+ // Only look for stacks on our virtual display.
+ if (stackInfo.displayId != displayId) {
+ continue;
+ }
+ // Found the topmost stack on target display.
+ return stackInfo;
+ }
+ return null;
+ }
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index e7ba85ad5d9e..566b38738dc1 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1189,13 +1189,11 @@ public final class BluetoothAdapter {
/**
* Factory reset bluetooth settings.
*
- * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}
- * permission
- *
* @return true to indicate that the config file was successfully cleared
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
public boolean factoryReset() {
try {
mServiceLock.readLock().lock();
@@ -1214,13 +1212,12 @@ public final class BluetoothAdapter {
/**
* Get the UUIDs supported by the local Bluetooth adapter.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
- *
* @return the UUIDs supported by the local Bluetooth Adapter.
* @hide
*/
@UnsupportedAppUsage
- public ParcelUuid[] getUuids() {
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public @NonNull ParcelUuid[] getUuids() {
if (getState() != STATE_ON) {
return null;
}
@@ -1476,7 +1473,6 @@ public final class BluetoothAdapter {
* will return false. After turning on Bluetooth,
* wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
* to get the updated value.
- * <p>Requires {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}
* <p>Applications cannot set the scan mode. They should use
* <code>startActivityForResult(
* BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
@@ -1488,8 +1484,8 @@ public final class BluetoothAdapter {
* @return true if the scan mode was set, false otherwise
* @hide
*/
- @UnsupportedAppUsage(publicAlternatives = "Use {@link #ACTION_REQUEST_DISCOVERABLE}, which "
- + "shows UI that confirms the user wants to go into discoverable mode.")
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public boolean setScanMode(@ScanMode int mode, int duration) {
if (getState() != STATE_ON) {
return false;
@@ -1507,9 +1503,34 @@ public final class BluetoothAdapter {
return false;
}
- /** @hide */
- @UnsupportedAppUsage
- public boolean setScanMode(int mode) {
+ /**
+ * Set the Bluetooth scan mode of the local Bluetooth adapter.
+ * <p>The Bluetooth scan mode determines if the local adapter is
+ * connectable and/or discoverable from remote Bluetooth devices.
+ * <p>For privacy reasons, discoverable mode is automatically turned off
+ * after <code>duration</code> seconds. For example, 120 seconds should be
+ * enough for a remote device to initiate and complete its discovery
+ * process.
+ * <p>Valid scan mode values are:
+ * {@link #SCAN_MODE_NONE},
+ * {@link #SCAN_MODE_CONNECTABLE},
+ * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
+ * <p>If Bluetooth state is not {@link #STATE_ON}, this API
+ * will return false. After turning on Bluetooth,
+ * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
+ * to get the updated value.
+ * <p>Applications cannot set the scan mode. They should use
+ * <code>startActivityForResult(
+ * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
+ * </code>instead.
+ *
+ * @param mode valid scan mode
+ * @return true if the scan mode was set, false otherwise
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ public boolean setScanMode(@ScanMode int mode) {
if (getState() != STATE_ON) {
return false;
}
@@ -1562,6 +1583,8 @@ public final class BluetoothAdapter {
* been called recently.
* @hide
*/
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public long getDiscoveryEndMillis() {
try {
mServiceLock.readLock().lock();
@@ -2060,7 +2083,7 @@ public final class BluetoothAdapter {
* BluetoothProfile}.
* @hide
*/
- public List<Integer> getSupportedProfiles() {
+ public @NonNull List<Integer> getSupportedProfiles() {
final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>();
try {
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 9cb73f931773..28cc1f8fc107 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -21,7 +21,10 @@ import static com.android.internal.util.Preconditions.checkNotNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.app.Activity;
import android.app.Application;
import android.app.PendingIntent;
@@ -29,9 +32,11 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.IntentSender;
import android.content.pm.PackageManager;
+import android.net.MacAddress;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
import android.util.Log;
@@ -252,6 +257,38 @@ public final class CompanionDeviceManager {
}
}
+ /**
+ * Check if a given package was {@link #associate associated} with a device with given
+ * mac address by given user.
+ *
+ * @param packageName the package to check for
+ * @param macAddress the mac address or BSSID of the device to check for
+ * @param user the user to check for
+ * @return whether a corresponding association record exists
+ *
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
+ public boolean isDeviceAssociated(
+ @NonNull String packageName,
+ @NonNull MacAddress macAddress,
+ @NonNull UserHandle user) {
+ if (!checkFeaturePresent()) {
+ return false;
+ }
+ checkNotNull(packageName, "package name cannot be null");
+ checkNotNull(macAddress, "mac address cannot be null");
+ checkNotNull(user, "user cannot be null");
+ try {
+ return mService.isDeviceAssociated(
+ packageName, macAddress.toString(), user.getIdentifier());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
private boolean checkFeaturePresent() {
boolean featurePresent = mService != null;
if (!featurePresent && DEBUG) {
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index 561342efb3ba..2e1ff0be8577 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -39,4 +39,6 @@ interface ICompanionDeviceManager {
boolean hasNotificationAccess(in ComponentName component);
PendingIntent requestNotificationAccess(in ComponentName component);
+
+ boolean isDeviceAssociated(in String packageName, in String macAddress, int userId);
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 862ec5098d9a..0b0fe798190c 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4762,6 +4762,13 @@ public abstract class Context {
/**
* Use with {@link #getSystemService(String)} to retrieve an
+ * {@link android.telephony.ims.ImsManager}.
+ * @hide
+ */
+ public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
+
+ /**
+ * Use with {@link #getSystemService(String)} to retrieve an
* {@link android.telephony.ims.RcsMessageManager}.
* @hide
*/
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 617401826750..714e9fb3ab05 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -929,6 +929,12 @@ public class ContextWrapper extends Context {
return mBase.getUserId();
}
+ /** @hide */
+ @Override
+ public UserHandle getUser() {
+ return mBase.getUser();
+ }
+
@Override
public Context createConfigurationContext(Configuration overrideConfiguration) {
return mBase.createConfigurationContext(overrideConfiguration);
diff --git a/core/java/android/content/SyncStats.java b/core/java/android/content/SyncStats.java
index 03b2250edee1..9596a6016c44 100644
--- a/core/java/android/content/SyncStats.java
+++ b/core/java/android/content/SyncStats.java
@@ -58,7 +58,7 @@ public class SyncStats implements Parcelable {
* attempted to update or delete a version of a resource on the server. This is expected
* to clear itself automatically once the new state is retrieved from the server,
* though it may remain until the user intervenes manually, perhaps by clearing the
- * local storage and starting over frmo scratch. This is considered a hard error.
+ * local storage and starting over from scratch. This is considered a hard error.
*/
public long numConflictDetectedExceptions;
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index 535bf675cd0e..64f20b839a63 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -49,8 +49,8 @@ import java.util.concurrent.CountDownLatch;
* limited to a local network over Multicast DNS. DNS service discovery is described at
* http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt
*
- * <p> The API is asynchronous and responses to requests from an application are on listener
- * callbacks on a seperate internal thread.
+ * <p> The API is asynchronous, and responses to requests from an application are on listener
+ * callbacks on a separate internal thread.
*
* <p> There are three main operations the API supports - registration, discovery and resolution.
* <pre>
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index d259f386ea77..b37e176ddb6e 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -38,9 +38,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
/**
- * <p>AsyncTask enables proper and easy use of the UI thread. This class allows you
- * to perform background operations and publish results on the UI thread without
- * having to manipulate threads and/or handlers.</p>
+ * <p>AsyncTask was intended to enable proper and easy use of the UI thread. However, the most
+ * common use case was for integrating into UI, and that would cause Context leaks, missed
+ * callbacks, or crashes on configuration changes. It also has inconsistent behavior on different
+ * versions of the platform, swallows exceptions from {@code doInBackground}, and does not provide
+ * much utility over using {@link Executor}s directly.</p>
*
* <p>AsyncTask is designed to be a helper class around {@link Thread} and {@link Handler}
* and does not constitute a generic threading framework. AsyncTasks should ideally be
@@ -188,7 +190,12 @@ import java.util.concurrent.atomic.AtomicInteger;
* <p>If you truly want parallel execution, you can invoke
* {@link #executeOnExecutor(java.util.concurrent.Executor, Object[])} with
* {@link #THREAD_POOL_EXECUTOR}.</p>
+ *
+ * @deprecated Use the standard <code>java.util.concurrent</code> or
+ * <a href="https://developer.android.com/topic/libraries/architecture/coroutines">
+ * Kotlin concurrency utilities</a> instead.
*/
+@Deprecated
public abstract class AsyncTask<Params, Progress, Result> {
private static final String LOG_TAG = "AsyncTask";
@@ -240,7 +247,13 @@ public abstract class AsyncTask<Params, Progress, Result> {
/**
* An {@link Executor} that can be used to execute tasks in parallel.
+ *
+ * @deprecated Using a single thread pool for a general purpose results in suboptimal behavior
+ * for different tasks. Small, CPU-bound tasks benefit from a bounded pool and queueing, and
+ * long-running blocking tasks, such as network operations, benefit from many threads. Use or
+ * create an {@link Executor} configured for your use case.
*/
+ @Deprecated
public static final Executor THREAD_POOL_EXECUTOR;
static {
@@ -254,7 +267,10 @@ public abstract class AsyncTask<Params, Progress, Result> {
/**
* An {@link Executor} that executes tasks one at a time in serial
* order. This serialization is global to a particular process.
+ *
+ * @deprecated Globally serializing tasks results in excessive queuing for unrelated operations.
*/
+ @Deprecated
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static final int MESSAGE_POST_RESULT = 0x1;
diff --git a/core/java/android/os/BasicShellCommandHandler.java b/core/java/android/os/BasicShellCommandHandler.java
new file mode 100644
index 000000000000..5bd5d61b6361
--- /dev/null
+++ b/core/java/android/os/BasicShellCommandHandler.java
@@ -0,0 +1,320 @@
+/*
+ * 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.os;
+
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+/**
+ * Helper for implementing {@link Binder#onShellCommand Binder.onShellCommand}. This is meant to
+ * be copied into mainline modules, so this class must not use any hidden APIs.
+ *
+ * @hide
+ */
+public abstract class BasicShellCommandHandler {
+ static final String TAG = "ShellCommand";
+ static final boolean DEBUG = false;
+
+ private Binder mTarget;
+ private FileDescriptor mIn;
+ private FileDescriptor mOut;
+ private FileDescriptor mErr;
+ private String[] mArgs;
+
+ private String mCmd;
+ private int mArgPos;
+ private String mCurArgData;
+
+ private FileInputStream mFileIn;
+ private FileOutputStream mFileOut;
+ private FileOutputStream mFileErr;
+
+ private PrintWriter mOutPrintWriter;
+ private PrintWriter mErrPrintWriter;
+ private InputStream mInputStream;
+
+ public void init(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ String[] args, int firstArgPos) {
+ mTarget = target;
+ mIn = in;
+ mOut = out;
+ mErr = err;
+ mArgs = args;
+ mCmd = null;
+ mArgPos = firstArgPos;
+ mCurArgData = null;
+ mFileIn = null;
+ mFileOut = null;
+ mFileErr = null;
+ mOutPrintWriter = null;
+ mErrPrintWriter = null;
+ mInputStream = null;
+ }
+
+ public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ String[] args) {
+ String cmd;
+ int start;
+ if (args != null && args.length > 0) {
+ cmd = args[0];
+ start = 1;
+ } else {
+ cmd = null;
+ start = 0;
+ }
+ init(target, in, out, err, args, start);
+ mCmd = cmd;
+
+ if (DEBUG) {
+ RuntimeException here = new RuntimeException("here");
+ here.fillInStackTrace();
+ Log.d(TAG, "Starting command " + mCmd + " on " + mTarget, here);
+ Log.d(TAG, "Calling uid=" + Binder.getCallingUid()
+ + " pid=" + Binder.getCallingPid());
+ }
+ int res = -1;
+ try {
+ res = onCommand(mCmd);
+ if (DEBUG) Log.d(TAG, "Executed command " + mCmd + " on " + mTarget);
+ } catch (Throwable e) {
+ // Unlike usual calls, in this case if an exception gets thrown
+ // back to us we want to print it back in to the dump data, since
+ // that is where the caller expects all interesting information to
+ // go.
+ PrintWriter eout = getErrPrintWriter();
+ eout.println();
+ eout.println("Exception occurred while executing: " + e.getMessage());
+ e.printStackTrace(eout);
+ } finally {
+ if (DEBUG) Log.d(TAG, "Flushing output streams on " + mTarget);
+ if (mOutPrintWriter != null) {
+ mOutPrintWriter.flush();
+ }
+ if (mErrPrintWriter != null) {
+ mErrPrintWriter.flush();
+ }
+ if (DEBUG) Log.d(TAG, "Sending command result on " + mTarget);
+ }
+ if (DEBUG) Log.d(TAG, "Finished command " + mCmd + " on " + mTarget);
+ return res;
+ }
+
+ /**
+ * Return the raw FileDescriptor for the output stream.
+ */
+ public FileDescriptor getOutFileDescriptor() {
+ return mOut;
+ }
+
+ /**
+ * Return direct raw access (not buffered) to the command's output data stream.
+ */
+ public OutputStream getRawOutputStream() {
+ if (mFileOut == null) {
+ mFileOut = new FileOutputStream(mOut);
+ }
+ return mFileOut;
+ }
+
+ /**
+ * Return a PrintWriter for formatting output to {@link #getRawOutputStream()}.
+ */
+ public PrintWriter getOutPrintWriter() {
+ if (mOutPrintWriter == null) {
+ mOutPrintWriter = new PrintWriter(getRawOutputStream());
+ }
+ return mOutPrintWriter;
+ }
+
+ /**
+ * Return the raw FileDescriptor for the error stream.
+ */
+ public FileDescriptor getErrFileDescriptor() {
+ return mErr;
+ }
+
+ /**
+ * Return direct raw access (not buffered) to the command's error output data stream.
+ */
+ public OutputStream getRawErrorStream() {
+ if (mFileErr == null) {
+ mFileErr = new FileOutputStream(mErr);
+ }
+ return mFileErr;
+ }
+
+ /**
+ * Return a PrintWriter for formatting output to {@link #getRawErrorStream()}.
+ */
+ public PrintWriter getErrPrintWriter() {
+ if (mErr == null) {
+ return getOutPrintWriter();
+ }
+ if (mErrPrintWriter == null) {
+ mErrPrintWriter = new PrintWriter(getRawErrorStream());
+ }
+ return mErrPrintWriter;
+ }
+
+ /**
+ * Return the raw FileDescriptor for the input stream.
+ */
+ public FileDescriptor getInFileDescriptor() {
+ return mIn;
+ }
+
+ /**
+ * Return direct raw access (not buffered) to the command's input data stream.
+ */
+ public InputStream getRawInputStream() {
+ if (mFileIn == null) {
+ mFileIn = new FileInputStream(mIn);
+ }
+ return mFileIn;
+ }
+
+ /**
+ * Return buffered access to the command's {@link #getRawInputStream()}.
+ */
+ public InputStream getBufferedInputStream() {
+ if (mInputStream == null) {
+ mInputStream = new BufferedInputStream(getRawInputStream());
+ }
+ return mInputStream;
+ }
+
+ /**
+ * Return the next option on the command line -- that is an argument that
+ * starts with '-'. If the next argument is not an option, null is returned.
+ */
+ public String getNextOption() {
+ if (mCurArgData != null) {
+ String prev = mArgs[mArgPos - 1];
+ throw new IllegalArgumentException("No argument expected after \"" + prev + "\"");
+ }
+ if (mArgPos >= mArgs.length) {
+ return null;
+ }
+ String arg = mArgs[mArgPos];
+ if (!arg.startsWith("-")) {
+ return null;
+ }
+ mArgPos++;
+ if (arg.equals("--")) {
+ return null;
+ }
+ if (arg.length() > 1 && arg.charAt(1) != '-') {
+ if (arg.length() > 2) {
+ mCurArgData = arg.substring(2);
+ return arg.substring(0, 2);
+ } else {
+ mCurArgData = null;
+ return arg;
+ }
+ }
+ mCurArgData = null;
+ return arg;
+ }
+
+ /**
+ * Return the next argument on the command line, whatever it is; if there are
+ * no arguments left, return null.
+ */
+ public String getNextArg() {
+ if (mCurArgData != null) {
+ String arg = mCurArgData;
+ mCurArgData = null;
+ return arg;
+ } else if (mArgPos < mArgs.length) {
+ return mArgs[mArgPos++];
+ } else {
+ return null;
+ }
+ }
+
+ public String peekNextArg() {
+ if (mCurArgData != null) {
+ return mCurArgData;
+ } else if (mArgPos < mArgs.length) {
+ return mArgs[mArgPos];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Return the next argument on the command line, whatever it is; if there are
+ * no arguments left, throws an IllegalArgumentException to report this to the user.
+ */
+ public String getNextArgRequired() {
+ String arg = getNextArg();
+ if (arg == null) {
+ String prev = mArgs[mArgPos - 1];
+ throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
+ }
+ return arg;
+ }
+
+ public int handleDefaultCommands(String cmd) {
+ if (cmd == null || "help".equals(cmd) || "-h".equals(cmd)) {
+ onHelp();
+ } else {
+ getOutPrintWriter().println("Unknown command: " + cmd);
+ }
+ return -1;
+ }
+
+ public Binder getTarget() {
+ return mTarget;
+ }
+
+ public String[] getAllArgs() {
+ return mArgs;
+ }
+
+ /**
+ * Implement parsing and execution of a command. If it isn't a command you understand,
+ * call {@link #handleDefaultCommands(String)} and return its result as a last resort.
+ * Use {@link #getNextOption()}, {@link #getNextArg()}, and {@link #getNextArgRequired()}
+ * to process additional command line arguments. Command output can be written to
+ * {@link #getOutPrintWriter()} and errors to {@link #getErrPrintWriter()}.
+ *
+ * <p class="caution">Note that no permission checking has been done before entering this
+ * function, so you need to be sure to do your own security verification for any commands you
+ * are executing. The easiest way to do this is to have the ShellCommand contain
+ * only a reference to your service's aidl interface, and do all of your command
+ * implementations on top of that -- that way you can rely entirely on your executing security
+ * code behind that interface.</p>
+ *
+ * @param cmd The first command line argument representing the name of the command to execute.
+ * @return Return the command result; generally 0 or positive indicates success and
+ * negative values indicate error.
+ */
+ public abstract int onCommand(String cmd);
+
+ /**
+ * Implement this to print help text about your command to {@link #getOutPrintWriter()}.
+ */
+ public abstract void onHelp();
+}
diff --git a/core/java/android/os/BatteryStatsManager.java b/core/java/android/os/BatteryStatsManager.java
index 367a868ddef4..e5650aea0522 100644
--- a/core/java/android/os/BatteryStatsManager.java
+++ b/core/java/android/os/BatteryStatsManager.java
@@ -23,6 +23,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
+import android.os.connectivity.CellularBatteryStats;
import android.os.connectivity.WifiBatteryStats;
import com.android.internal.app.IBatteryStats;
@@ -158,6 +159,21 @@ public class BatteryStatsManager {
}
/**
+ * Retrieves all the cellular related battery stats.
+ *
+ * @return Instance of {@link CellularBatteryStats}.
+ */
+ @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
+ public @NonNull CellularBatteryStats getCellularBatteryStats() {
+ try {
+ return mBatteryStats.getCellularBatteryStats();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return null;
+ }
+ }
+
+ /**
* Retrieves all the wifi related battery stats.
*
* @return Instance of {@link WifiBatteryStats}.
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index ef3afabfe878..fda1539b59f5 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -37,7 +37,9 @@ import libcore.io.IoUtils;
import libcore.util.NativeAllocationRegistry;
import java.io.FileDescriptor;
+import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Modifier;
@@ -905,11 +907,62 @@ public class Binder implements IBinder {
@Nullable FileDescriptor err,
@NonNull String[] args, @Nullable ShellCallback callback,
@NonNull ResultReceiver resultReceiver) throws RemoteException {
- FileOutputStream fout = new FileOutputStream(err != null ? err : out);
- PrintWriter pw = new FastPrintWriter(fout);
+
+ // First, convert in, out and err to @NonNull, by redirecting any that's null to /dev/null.
+ try {
+ if (in == null) {
+ in = new FileInputStream("/dev/null").getFD();
+ }
+ if (out == null) {
+ out = new FileOutputStream("/dev/null").getFD();
+ }
+ if (err == null) {
+ err = out;
+ }
+ } catch (IOException e) {
+ PrintWriter pw = new FastPrintWriter(new FileOutputStream(err != null ? err : out));
+ pw.println("Failed to open /dev/null: " + e.getMessage());
+ pw.flush();
+ resultReceiver.send(-1, null);
+ return;
+ }
+ // Also make args @NonNull.
+ if (args == null) {
+ args = new String[0];
+ }
+
+ int result = -1;
+ try {
+ result = handleShellCommand(new ParcelFileDescriptor(in),
+ new ParcelFileDescriptor(out), new ParcelFileDescriptor(err), args);
+ } finally {
+ resultReceiver.send(result, null);
+ }
+ }
+
+ /**
+ * System services can implement this method to implement ADB shell commands.
+ *
+ * TODO More Javadoc.
+ * TODO Add a generic way to define subcommands and their permissions.
+ *
+ * @param in standard input.
+ * @param out standard output.
+ * @param err standard error.
+ * @param args arguments passed to the command. Can be empty. The first argument is typically
+ * a subcommand, such as {@code run} for {@code adb shell cmd jobscheduler run}.
+ *
+ * @hide
+ */
+ // @SystemApi TODO Make it a system API.
+ protected int handleShellCommand(@NonNull ParcelFileDescriptor in,
+ @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
+ @NonNull String[] args) {
+ FileOutputStream ferr = new FileOutputStream(err.getFileDescriptor());
+ PrintWriter pw = new FastPrintWriter(ferr);
pw.println("No shell command implementation.");
pw.flush();
- resultReceiver.send(0, null);
+ return 0;
}
/**
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index bc32df42ea4f..563492925ff0 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -1754,6 +1754,8 @@ public final class Debug
* such runtime statistic exists.
*
* <p>The following table lists the runtime statistics that the runtime supports.
+ * All statistics are approximate. Individual allocations may not be immediately reflected
+ * in the results.
* Note runtime statistics may be added or removed in a future API level.</p>
*
* <table>
diff --git a/core/java/android/os/ShellCommand.java b/core/java/android/os/ShellCommand.java
index 2fe8726a0915..f3a6869687dc 100644
--- a/core/java/android/os/ShellCommand.java
+++ b/core/java/android/os/ShellCommand.java
@@ -33,105 +33,21 @@ import java.io.PrintWriter;
* Helper for implementing {@link Binder#onShellCommand Binder.onShellCommand}.
* @hide
*/
-public abstract class ShellCommand {
- static final String TAG = "ShellCommand";
- static final boolean DEBUG = false;
-
- private Binder mTarget;
- private FileDescriptor mIn;
- private FileDescriptor mOut;
- private FileDescriptor mErr;
- private String[] mArgs;
+public abstract class ShellCommand extends BasicShellCommandHandler {
private ShellCallback mShellCallback;
private ResultReceiver mResultReceiver;
- private String mCmd;
- private int mArgPos;
- private String mCurArgData;
-
- private FileInputStream mFileIn;
- private FileOutputStream mFileOut;
- private FileOutputStream mFileErr;
-
- private FastPrintWriter mOutPrintWriter;
- private FastPrintWriter mErrPrintWriter;
- private InputStream mInputStream;
-
- public void init(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ShellCallback callback, int firstArgPos) {
- mTarget = target;
- mIn = in;
- mOut = out;
- mErr = err;
- mArgs = args;
- mShellCallback = callback;
- mResultReceiver = null;
- mCmd = null;
- mArgPos = firstArgPos;
- mCurArgData = null;
- mFileIn = null;
- mFileOut = null;
- mFileErr = null;
- mOutPrintWriter = null;
- mErrPrintWriter = null;
- mInputStream = null;
- }
-
public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
- String cmd;
- int start;
- if (args != null && args.length > 0) {
- cmd = args[0];
- start = 1;
- } else {
- cmd = null;
- start = 0;
- }
- init(target, in, out, err, args, callback, start);
- mCmd = cmd;
+ mShellCallback = callback;
mResultReceiver = resultReceiver;
+ final int result = super.exec(target, in, out, err, args);
- if (DEBUG) {
- RuntimeException here = new RuntimeException("here");
- here.fillInStackTrace();
- Slog.d(TAG, "Starting command " + mCmd + " on " + mTarget, here);
- Slog.d(TAG, "Calling uid=" + Binder.getCallingUid()
- + " pid=" + Binder.getCallingPid() + " ShellCallback=" + getShellCallback());
+ if (mResultReceiver != null) {
+ mResultReceiver.send(result, null);
}
- int res = -1;
- try {
- res = onCommand(mCmd);
- if (DEBUG) Slog.d(TAG, "Executed command " + mCmd + " on " + mTarget);
- } catch (SecurityException e) {
- PrintWriter eout = getErrPrintWriter();
- eout.println("Security exception: " + e.getMessage());
- eout.println();
- e.printStackTrace(eout);
- } catch (Throwable e) {
- // Unlike usual calls, in this case if an exception gets thrown
- // back to us we want to print it back in to the dump data, since
- // that is where the caller expects all interesting information to
- // go.
- PrintWriter eout = getErrPrintWriter();
- eout.println();
- eout.println("Exception occurred while executing:");
- e.printStackTrace(eout);
- } finally {
- if (DEBUG) Slog.d(TAG, "Flushing output streams on " + mTarget);
- if (mOutPrintWriter != null) {
- mOutPrintWriter.flush();
- }
- if (mErrPrintWriter != null) {
- mErrPrintWriter.flush();
- }
- if (DEBUG) Slog.d(TAG, "Sending command result on " + mTarget);
- if (mResultReceiver != null) {
- mResultReceiver.send(res, null);
- }
- }
- if (DEBUG) Slog.d(TAG, "Finished command " + mCmd + " on " + mTarget);
- return res;
+
+ return result;
}
/**
@@ -146,90 +62,6 @@ public abstract class ShellCommand {
}
/**
- * Return the raw FileDescriptor for the output stream.
- */
- public FileDescriptor getOutFileDescriptor() {
- return mOut;
- }
-
- /**
- * Return direct raw access (not buffered) to the command's output data stream.
- */
- public OutputStream getRawOutputStream() {
- if (mFileOut == null) {
- mFileOut = new FileOutputStream(mOut);
- }
- return mFileOut;
- }
-
- /**
- * Return a PrintWriter for formatting output to {@link #getRawOutputStream()}.
- */
- public PrintWriter getOutPrintWriter() {
- if (mOutPrintWriter == null) {
- mOutPrintWriter = new FastPrintWriter(getRawOutputStream());
- }
- return mOutPrintWriter;
- }
-
- /**
- * Return the raw FileDescriptor for the error stream.
- */
- public FileDescriptor getErrFileDescriptor() {
- return mErr;
- }
-
- /**
- * Return direct raw access (not buffered) to the command's error output data stream.
- */
- public OutputStream getRawErrorStream() {
- if (mFileErr == null) {
- mFileErr = new FileOutputStream(mErr);
- }
- return mFileErr;
- }
-
- /**
- * Return a PrintWriter for formatting output to {@link #getRawErrorStream()}.
- */
- public PrintWriter getErrPrintWriter() {
- if (mErr == null) {
- return getOutPrintWriter();
- }
- if (mErrPrintWriter == null) {
- mErrPrintWriter = new FastPrintWriter(getRawErrorStream());
- }
- return mErrPrintWriter;
- }
-
- /**
- * Return the raw FileDescriptor for the input stream.
- */
- public FileDescriptor getInFileDescriptor() {
- return mIn;
- }
-
- /**
- * Return direct raw access (not buffered) to the command's input data stream.
- */
- public InputStream getRawInputStream() {
- if (mFileIn == null) {
- mFileIn = new FileInputStream(mIn);
- }
- return mFileIn;
- }
-
- /**
- * Return buffered access to the command's {@link #getRawInputStream()}.
- */
- public InputStream getBufferedInputStream() {
- if (mInputStream == null) {
- mInputStream = new BufferedInputStream(getRawInputStream());
- }
- return mInputStream;
- }
-
- /**
* Helper for just system services to ask the shell to open an output file.
* @hide
*/
@@ -256,77 +88,19 @@ public abstract class ShellCommand {
return null;
}
- /**
- * Return the next option on the command line -- that is an argument that
- * starts with '-'. If the next argument is not an option, null is returned.
- */
- public String getNextOption() {
- if (mCurArgData != null) {
- String prev = mArgs[mArgPos - 1];
- throw new IllegalArgumentException("No argument expected after \"" + prev + "\"");
- }
- if (mArgPos >= mArgs.length) {
- return null;
- }
- String arg = mArgs[mArgPos];
- if (!arg.startsWith("-")) {
- return null;
- }
- mArgPos++;
- if (arg.equals("--")) {
- return null;
- }
- if (arg.length() > 1 && arg.charAt(1) != '-') {
- if (arg.length() > 2) {
- mCurArgData = arg.substring(2);
- return arg.substring(0, 2);
- } else {
- mCurArgData = null;
- return arg;
- }
- }
- mCurArgData = null;
- return arg;
- }
-
- /**
- * Return the next argument on the command line, whatever it is; if there are
- * no arguments left, return null.
- */
- public String getNextArg() {
- if (mCurArgData != null) {
- String arg = mCurArgData;
- mCurArgData = null;
- return arg;
- } else if (mArgPos < mArgs.length) {
- return mArgs[mArgPos++];
- } else {
- return null;
+ public int handleDefaultCommands(String cmd) {
+ if ("dump".equals(cmd)) {
+ String[] newArgs = new String[getAllArgs().length-1];
+ System.arraycopy(getAllArgs(), 1, newArgs, 0, getAllArgs().length-1);
+ getTarget().doDump(getOutFileDescriptor(), getOutPrintWriter(), newArgs);
+ return 0;
}
+ return super.handleDefaultCommands(cmd);
}
@UnsupportedAppUsage
public String peekNextArg() {
- if (mCurArgData != null) {
- return mCurArgData;
- } else if (mArgPos < mArgs.length) {
- return mArgs[mArgPos];
- } else {
- return null;
- }
- }
-
- /**
- * Return the next argument on the command line, whatever it is; if there are
- * no arguments left, throws an IllegalArgumentException to report this to the user.
- */
- public String getNextArgRequired() {
- String arg = getNextArg();
- if (arg == null) {
- String prev = mArgs[mArgPos - 1];
- throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
- }
- return arg;
+ return super.peekNextArg();
}
/**
@@ -335,43 +109,4 @@ public abstract class ShellCommand {
public ShellCallback getShellCallback() {
return mShellCallback;
}
-
- public int handleDefaultCommands(String cmd) {
- if ("dump".equals(cmd)) {
- String[] newArgs = new String[mArgs.length-1];
- System.arraycopy(mArgs, 1, newArgs, 0, mArgs.length-1);
- mTarget.doDump(mOut, getOutPrintWriter(), newArgs);
- return 0;
- } else if (cmd == null || "help".equals(cmd) || "-h".equals(cmd)) {
- onHelp();
- } else {
- getOutPrintWriter().println("Unknown command: " + cmd);
- }
- return -1;
- }
-
- /**
- * Implement parsing and execution of a command. If it isn't a command you understand,
- * call {@link #handleDefaultCommands(String)} and return its result as a last resort.
- * Use {@link #getNextOption()}, {@link #getNextArg()}, and {@link #getNextArgRequired()}
- * to process additional command line arguments. Command output can be written to
- * {@link #getOutPrintWriter()} and errors to {@link #getErrPrintWriter()}.
- *
- * <p class="caution">Note that no permission checking has been done before entering this function,
- * so you need to be sure to do your own security verification for any commands you
- * are executing. The easiest way to do this is to have the ShellCommand contain
- * only a reference to your service's aidl interface, and do all of your command
- * implementations on top of that -- that way you can rely entirely on your executing security
- * code behind that interface.</p>
- *
- * @param cmd The first command line argument representing the name of the command to execute.
- * @return Return the command result; generally 0 or positive indicates success and
- * negative values indicate error.
- */
- public abstract int onCommand(String cmd);
-
- /**
- * Implement this to print help text about your command to {@link #getOutPrintWriter()}.
- */
- public abstract void onHelp();
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 3476b18ceee0..b096049ebb68 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2486,6 +2486,8 @@ public class UserManager {
/**
* Return the number of users currently created on the device.
+ * <p>This API is not for use by third-party apps. It requires the {@code MANAGE_USERS}
+ * permission.</p>
*/
public int getUserCount() {
List<UserInfo> users = getUsers();
diff --git a/core/java/android/os/connectivity/CellularBatteryStats.java b/core/java/android/os/connectivity/CellularBatteryStats.java
index 2e0904048d40..caa406899161 100644
--- a/core/java/android/os/connectivity/CellularBatteryStats.java
+++ b/core/java/android/os/connectivity/CellularBatteryStats.java
@@ -15,241 +15,367 @@
*/
package android.os.connectivity;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.BatteryStats;
import android.os.Parcel;
import android.os.Parcelable;
-
+import android.telephony.Annotation.NetworkType;
import android.telephony.ModemActivityInfo;
import android.telephony.SignalStrength;
import java.util.Arrays;
+import java.util.Objects;
/**
* API for Cellular power stats
*
* @hide
*/
+@SystemApi
public final class CellularBatteryStats implements Parcelable {
- private long mLoggingDurationMs;
- private long mKernelActiveTimeMs;
- private long mNumPacketsTx;
- private long mNumBytesTx;
- private long mNumPacketsRx;
- private long mNumBytesRx;
- private long mSleepTimeMs;
- private long mIdleTimeMs;
- private long mRxTimeMs;
- private long mEnergyConsumedMaMs;
- private long[] mTimeInRatMs;
- private long[] mTimeInRxSignalStrengthLevelMs;
- private long[] mTxTimeMs;
- private long mMonitoredRailChargeConsumedMaMs;
-
- public static final @android.annotation.NonNull Parcelable.Creator<CellularBatteryStats> CREATOR = new
- Parcelable.Creator<CellularBatteryStats>() {
- public CellularBatteryStats createFromParcel(Parcel in) {
- return new CellularBatteryStats(in);
- }
-
- public CellularBatteryStats[] newArray(int size) {
- return new CellularBatteryStats[size];
- }
- };
-
- public CellularBatteryStats() {
- initialize();
- }
-
- public void writeToParcel(Parcel out, int flags) {
- out.writeLong(mLoggingDurationMs);
- out.writeLong(mKernelActiveTimeMs);
- out.writeLong(mNumPacketsTx);
- out.writeLong(mNumBytesTx);
- out.writeLong(mNumPacketsRx);
- out.writeLong(mNumBytesRx);
- out.writeLong(mSleepTimeMs);
- out.writeLong(mIdleTimeMs);
- out.writeLong(mRxTimeMs);
- out.writeLong(mEnergyConsumedMaMs);
- out.writeLongArray(mTimeInRatMs);
- out.writeLongArray(mTimeInRxSignalStrengthLevelMs);
- out.writeLongArray(mTxTimeMs);
- out.writeLong(mMonitoredRailChargeConsumedMaMs);
- }
-
- public void readFromParcel(Parcel in) {
- mLoggingDurationMs = in.readLong();
- mKernelActiveTimeMs = in.readLong();
- mNumPacketsTx = in.readLong();
- mNumBytesTx = in.readLong();
- mNumPacketsRx = in.readLong();
- mNumBytesRx = in.readLong();
- mSleepTimeMs = in.readLong();
- mIdleTimeMs = in.readLong();
- mRxTimeMs = in.readLong();
- mEnergyConsumedMaMs = in.readLong();
- in.readLongArray(mTimeInRatMs);
- in.readLongArray(mTimeInRxSignalStrengthLevelMs);
- in.readLongArray(mTxTimeMs);
- mMonitoredRailChargeConsumedMaMs = in.readLong();
- }
-
- public long getLoggingDurationMs() {
- return mLoggingDurationMs;
- }
-
- public long getKernelActiveTimeMs() {
- return mKernelActiveTimeMs;
- }
-
- public long getNumPacketsTx() {
- return mNumPacketsTx;
- }
-
- public long getNumBytesTx() {
- return mNumBytesTx;
- }
-
- public long getNumPacketsRx() {
- return mNumPacketsRx;
- }
-
- public long getNumBytesRx() {
- return mNumBytesRx;
- }
-
- public long getSleepTimeMs() {
- return mSleepTimeMs;
- }
-
- public long getIdleTimeMs() {
- return mIdleTimeMs;
- }
-
- public long getRxTimeMs() {
- return mRxTimeMs;
- }
-
- public long getEnergyConsumedMaMs() {
- return mEnergyConsumedMaMs;
- }
-
- public long[] getTimeInRatMs() {
- return mTimeInRatMs;
- }
-
- public long[] getTimeInRxSignalStrengthLevelMs() {
- return mTimeInRxSignalStrengthLevelMs;
- }
-
- public long[] getTxTimeMs() {
- return mTxTimeMs;
- }
-
- public long getMonitoredRailChargeConsumedMaMs() {
- return mMonitoredRailChargeConsumedMaMs;
- }
-
- public void setLoggingDurationMs(long t) {
- mLoggingDurationMs = t;
- return;
- }
-
- public void setKernelActiveTimeMs(long t) {
- mKernelActiveTimeMs = t;
- return;
- }
-
- public void setNumPacketsTx(long n) {
- mNumPacketsTx = n;
- return;
- }
-
- public void setNumBytesTx(long b) {
- mNumBytesTx = b;
- return;
- }
-
- public void setNumPacketsRx(long n) {
- mNumPacketsRx = n;
- return;
- }
-
- public void setNumBytesRx(long b) {
- mNumBytesRx = b;
- return;
- }
-
- public void setSleepTimeMs(long t) {
- mSleepTimeMs = t;
- return;
- }
-
- public void setIdleTimeMs(long t) {
- mIdleTimeMs = t;
- return;
- }
-
- public void setRxTimeMs(long t) {
- mRxTimeMs = t;
- return;
- }
-
- public void setEnergyConsumedMaMs(long e) {
- mEnergyConsumedMaMs = e;
- return;
- }
-
- public void setTimeInRatMs(long[] t) {
- mTimeInRatMs = Arrays.copyOfRange(t, 0,
- Math.min(t.length, BatteryStats.NUM_DATA_CONNECTION_TYPES));
- return;
- }
-
- public void setTimeInRxSignalStrengthLevelMs(long[] t) {
- mTimeInRxSignalStrengthLevelMs = Arrays.copyOfRange(t, 0,
- Math.min(t.length, SignalStrength.NUM_SIGNAL_STRENGTH_BINS));
- return;
- }
-
- public void setTxTimeMs(long[] t) {
- mTxTimeMs = Arrays.copyOfRange(t, 0, Math.min(t.length, ModemActivityInfo.TX_POWER_LEVELS));
- return;
- }
-
- public void setMonitoredRailChargeConsumedMaMs(long monitoredRailEnergyConsumedMaMs) {
- mMonitoredRailChargeConsumedMaMs = monitoredRailEnergyConsumedMaMs;
- return;
- }
-
- public int describeContents() {
- return 0;
- }
-
- private CellularBatteryStats(Parcel in) {
- initialize();
- readFromParcel(in);
- }
-
- private void initialize() {
- mLoggingDurationMs = 0;
- mKernelActiveTimeMs = 0;
- mNumPacketsTx = 0;
- mNumBytesTx = 0;
- mNumPacketsRx = 0;
- mNumBytesRx = 0;
- mSleepTimeMs = 0;
- mIdleTimeMs = 0;
- mRxTimeMs = 0;
- mEnergyConsumedMaMs = 0;
- mTimeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
- Arrays.fill(mTimeInRatMs, 0);
- mTimeInRxSignalStrengthLevelMs = new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
- Arrays.fill(mTimeInRxSignalStrengthLevelMs, 0);
- mTxTimeMs = new long[ModemActivityInfo.TX_POWER_LEVELS];
- Arrays.fill(mTxTimeMs, 0);
- mMonitoredRailChargeConsumedMaMs = 0;
- return;
- }
-} \ No newline at end of file
+ private long mLoggingDurationMs = 0;
+ private long mKernelActiveTimeMs = 0;
+ private long mNumPacketsTx = 0;
+ private long mNumBytesTx = 0;
+ private long mNumPacketsRx = 0;
+ private long mNumBytesRx = 0;
+ private long mSleepTimeMs = 0;
+ private long mIdleTimeMs = 0;
+ private long mRxTimeMs = 0;
+ private long mEnergyConsumedMaMs = 0;
+ private long[] mTimeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
+ private long[] mTimeInRxSignalStrengthLevelMs =
+ new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
+ private long[] mTxTimeMs = new long[ModemActivityInfo.TX_POWER_LEVELS];
+ private long mMonitoredRailChargeConsumedMaMs = 0;
+
+ public static final @NonNull Parcelable.Creator<CellularBatteryStats> CREATOR =
+ new Parcelable.Creator<CellularBatteryStats>() {
+ public CellularBatteryStats createFromParcel(Parcel in) {
+ return new CellularBatteryStats(in);
+ }
+
+ public CellularBatteryStats[] newArray(int size) {
+ return new CellularBatteryStats[size];
+ }
+ };
+
+ /** @hide **/
+ public CellularBatteryStats() {}
+
+ @Override
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeLong(mLoggingDurationMs);
+ out.writeLong(mKernelActiveTimeMs);
+ out.writeLong(mNumPacketsTx);
+ out.writeLong(mNumBytesTx);
+ out.writeLong(mNumPacketsRx);
+ out.writeLong(mNumBytesRx);
+ out.writeLong(mSleepTimeMs);
+ out.writeLong(mIdleTimeMs);
+ out.writeLong(mRxTimeMs);
+ out.writeLong(mEnergyConsumedMaMs);
+ out.writeLongArray(mTimeInRatMs);
+ out.writeLongArray(mTimeInRxSignalStrengthLevelMs);
+ out.writeLongArray(mTxTimeMs);
+ out.writeLong(mMonitoredRailChargeConsumedMaMs);
+ }
+
+ private void readFromParcel(Parcel in) {
+ mLoggingDurationMs = in.readLong();
+ mKernelActiveTimeMs = in.readLong();
+ mNumPacketsTx = in.readLong();
+ mNumBytesTx = in.readLong();
+ mNumPacketsRx = in.readLong();
+ mNumBytesRx = in.readLong();
+ mSleepTimeMs = in.readLong();
+ mIdleTimeMs = in.readLong();
+ mRxTimeMs = in.readLong();
+ mEnergyConsumedMaMs = in.readLong();
+ in.readLongArray(mTimeInRatMs);
+ in.readLongArray(mTimeInRxSignalStrengthLevelMs);
+ in.readLongArray(mTxTimeMs);
+ mMonitoredRailChargeConsumedMaMs = in.readLong();
+ }
+
+ @Override
+ public boolean equals(@Nullable Object other) {
+ if (!(other instanceof CellularBatteryStats)) return false;
+ if (other == this) return true;
+ CellularBatteryStats otherStats = (CellularBatteryStats) other;
+ return this.mLoggingDurationMs == otherStats.mLoggingDurationMs
+ && this.mKernelActiveTimeMs == otherStats.mKernelActiveTimeMs
+ && this.mNumPacketsTx == otherStats.mNumPacketsTx
+ && this.mNumBytesTx == otherStats.mNumBytesTx
+ && this.mNumPacketsRx == otherStats.mNumPacketsRx
+ && this.mNumBytesRx == otherStats.mNumBytesRx
+ && this.mSleepTimeMs == otherStats.mSleepTimeMs
+ && this.mIdleTimeMs == otherStats.mIdleTimeMs
+ && this.mRxTimeMs == otherStats.mRxTimeMs
+ && this.mEnergyConsumedMaMs == otherStats.mEnergyConsumedMaMs
+ && Arrays.equals(this.mTimeInRatMs, otherStats.mTimeInRatMs)
+ && Arrays.equals(this.mTimeInRxSignalStrengthLevelMs,
+ otherStats.mTimeInRxSignalStrengthLevelMs)
+ && Arrays.equals(this.mTxTimeMs, otherStats.mTxTimeMs)
+ && this.mMonitoredRailChargeConsumedMaMs
+ == otherStats.mMonitoredRailChargeConsumedMaMs;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mLoggingDurationMs, mKernelActiveTimeMs, mNumPacketsTx,
+ mNumBytesTx, mNumPacketsRx, mNumBytesRx, mSleepTimeMs, mIdleTimeMs,
+ mRxTimeMs, mEnergyConsumedMaMs, Arrays.hashCode(mTimeInRatMs),
+ Arrays.hashCode(mTimeInRxSignalStrengthLevelMs), Arrays.hashCode(mTxTimeMs),
+ mMonitoredRailChargeConsumedMaMs);
+ }
+
+ /**
+ * Returns the duration for which these cellular stats were collected.
+ *
+ * @return Duration of stats collection in milliseconds.
+ */
+ public long getLoggingDurationMillis() {
+ return mLoggingDurationMs;
+ }
+
+ /**
+ * Returns the duration for which the kernel was active within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Duration of kernel active time in milliseconds.
+ */
+ public long getKernelActiveTimeMillis() {
+ return mKernelActiveTimeMs;
+ }
+
+ /**
+ * Returns the number of packets transmitted over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Number of packets transmitted.
+ */
+ public long getNumPacketsTx() {
+ return mNumPacketsTx;
+ }
+
+ /**
+ * Returns the number of packets received over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Number of packets received.
+ */
+ public long getNumBytesTx() {
+ return mNumBytesTx;
+ }
+
+ /**
+ * Returns the number of bytes transmitted over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Number of bytes transmitted.
+ */
+ public long getNumPacketsRx() {
+ return mNumPacketsRx;
+ }
+
+ /**
+ * Returns the number of bytes received over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Number of bytes received.
+ */
+ public long getNumBytesRx() {
+ return mNumBytesRx;
+ }
+
+ /**
+ * Returns the duration for which the device was sleeping within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Duration of sleep time in milliseconds.
+ */
+ public long getSleepTimeMillis() {
+ return mSleepTimeMs;
+ }
+
+ /**
+ * Returns the duration for which the device was idle within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Duration of idle time in milliseconds.
+ */
+ public long getIdleTimeMillis() {
+ return mIdleTimeMs;
+ }
+
+ /**
+ * Returns the duration for which the device was receiving over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Duration of cellular reception time in milliseconds.
+ */
+ public long getRxTimeMillis() {
+ return mRxTimeMs;
+ }
+
+ /**
+ * Returns an estimation of energy consumed by cellular chip within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Energy consumed in milli-ampere milliseconds (mAmS).
+ */
+ public long getEnergyConsumedMaMillis() {
+ return mEnergyConsumedMaMs;
+ }
+
+ /**
+ * Returns the time in microseconds that the phone has been running with
+ * the given data connection.
+ *
+ * @return Amount of time phone spends in various Radio Access Technologies in microseconds.
+ * The index is {@link NetworkType}.
+ */
+ @NonNull
+ public long[] getTimeInRatMicros() {
+ return mTimeInRatMs;
+ }
+
+ /**
+ * Returns the time in microseconds that the phone has been running with
+ * the given signal strength.
+ *
+ * @return Amount of time phone spends in various cellular rx signal strength levels
+ * in microseconds. The index is signal strength bin.
+ */
+ @NonNull
+ public long[] getTimeInRxSignalStrengthLevelMicros() {
+ return mTimeInRxSignalStrengthLevelMs;
+ }
+
+ /**
+ * Returns the duration for which the device was transmitting over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Duration of cellular transmission time in milliseconds.
+ * Tx(transmit) power index below
+ * <ul>
+ * <li> index 0 = tx_power < 0dBm. </li>
+ * <li> index 1 = 0dBm < tx_power < 5dBm. </li>
+ * <li> index 2 = 5dBm < tx_power < 15dBm. </li>
+ * <li> index 3 = 15dBm < tx_power < 20dBm. </li>
+ * <li> index 4 = tx_power > 20dBm. </li>
+ * </ul>
+ */
+ @NonNull
+ public long[] getTxTimeMillis() {
+ return mTxTimeMs;
+ }
+
+ /**
+ * Returns the energy consumed by cellular chip within {@link #getLoggingDurationMillis()}.
+ *
+ * @return Energy consumed in milli-ampere milli-seconds (mAmS).
+ */
+ public long getMonitoredRailChargeConsumedMaMillis() {
+ return mMonitoredRailChargeConsumedMaMs;
+ }
+
+ /** @hide **/
+ public void setLoggingDurationMillis(long t) {
+ mLoggingDurationMs = t;
+ return;
+ }
+
+ /** @hide **/
+ public void setKernelActiveTimeMillis(long t) {
+ mKernelActiveTimeMs = t;
+ return;
+ }
+
+ /** @hide **/
+ public void setNumPacketsTx(long n) {
+ mNumPacketsTx = n;
+ return;
+ }
+
+ /** @hide **/
+ public void setNumBytesTx(long b) {
+ mNumBytesTx = b;
+ return;
+ }
+
+ /** @hide **/
+ public void setNumPacketsRx(long n) {
+ mNumPacketsRx = n;
+ return;
+ }
+
+ /** @hide **/
+ public void setNumBytesRx(long b) {
+ mNumBytesRx = b;
+ return;
+ }
+
+ /** @hide **/
+ public void setSleepTimeMillis(long t) {
+ mSleepTimeMs = t;
+ return;
+ }
+
+ /** @hide **/
+ public void setIdleTimeMillis(long t) {
+ mIdleTimeMs = t;
+ return;
+ }
+
+ /** @hide **/
+ public void setRxTimeMillis(long t) {
+ mRxTimeMs = t;
+ return;
+ }
+
+ /** @hide **/
+ public void setEnergyConsumedMaMillis(long e) {
+ mEnergyConsumedMaMs = e;
+ return;
+ }
+
+ /** @hide **/
+ public void setTimeInRatMicros(@NonNull long[] t) {
+ mTimeInRatMs = Arrays.copyOfRange(t, 0,
+ Math.min(t.length, BatteryStats.NUM_DATA_CONNECTION_TYPES));
+ return;
+ }
+
+ /** @hide **/
+ public void setTimeInRxSignalStrengthLevelMicros(@NonNull long[] t) {
+ mTimeInRxSignalStrengthLevelMs = Arrays.copyOfRange(t, 0,
+ Math.min(t.length, SignalStrength.NUM_SIGNAL_STRENGTH_BINS));
+ return;
+ }
+
+ /** @hide **/
+ public void setTxTimeMillis(@NonNull long[] t) {
+ mTxTimeMs = Arrays.copyOfRange(t, 0, Math.min(t.length, ModemActivityInfo.TX_POWER_LEVELS));
+ return;
+ }
+
+ /** @hide **/
+ public void setMonitoredRailChargeConsumedMaMillis(long monitoredRailEnergyConsumedMaMs) {
+ mMonitoredRailChargeConsumedMaMs = monitoredRailEnergyConsumedMaMs;
+ return;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ private CellularBatteryStats(Parcel in) {
+ readFromParcel(in);
+ }
+}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index b1fd4e5e699e..af1a51f68d71 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -47,8 +47,6 @@ public class FeatureFlagUtils {
static {
DEFAULT_FLAGS = new HashMap<>();
DEFAULT_FLAGS.put("settings_audio_switcher", "true");
- DEFAULT_FLAGS.put("settings_mobile_network_v2", "true");
- DEFAULT_FLAGS.put("settings_network_and_internet_v2", "true");
DEFAULT_FLAGS.put("settings_systemui_theme", "true");
DEFAULT_FLAGS.put(DYNAMIC_SYSTEM, "false");
DEFAULT_FLAGS.put(SEAMLESS_TRANSFER, "false");
diff --git a/core/java/android/util/StatsEvent.java b/core/java/android/util/StatsEvent.java
index 8d9607ff11e2..a21f9e09ced5 100644
--- a/core/java/android/util/StatsEvent.java
+++ b/core/java/android/util/StatsEvent.java
@@ -49,10 +49,12 @@ public final class StatsEvent {
// See android_util_StatsLog.cpp.
private static final int MAX_PAYLOAD_SIZE = LOGGER_ENTRY_MAX_PAYLOAD - 4;
+ private final int mAtomId;
private final Buffer mBuffer;
private final int mNumBytes;
- private StatsEvent(@NonNull final Buffer buffer, final int numBytes) {
+ private StatsEvent(final int atomId, @NonNull final Buffer buffer, final int numBytes) {
+ mAtomId = atomId;
mBuffer = buffer;
mNumBytes = numBytes;
}
@@ -65,6 +67,10 @@ public final class StatsEvent {
return new StatsEvent.Builder(Buffer.obtain());
}
+ int getAtomId() {
+ return mAtomId;
+ }
+
@NonNull
byte[] getBytes() {
return mBuffer.getBytes();
@@ -116,9 +122,10 @@ public final class StatsEvent {
private static final byte TYPE_LIST = 0x03;
private static final byte TYPE_FLOAT = 0x04;
private static final byte TYPE_BOOLEAN = 0x05;
- private static final byte TYPE_OBJECT = 0x06;
- private static final byte TYPE_BYTE_ARRAY = 0x07;
- private static final byte TYPE_ATTRIBUTION_CHAIN = 0x08;
+ private static final byte TYPE_BYTE_ARRAY = 0x06;
+ private static final byte TYPE_OBJECT = 0x07;
+ private static final byte TYPE_KEY_VALUE_PAIRS = 0x08;
+ private static final byte TYPE_ATTRIBUTION_CHAIN = 0x09;
private static final byte TYPE_ERRORS = 0x0F;
// Error flags.
@@ -126,17 +133,19 @@ public final class StatsEvent {
private static final int ERROR_NO_ATOM_ID = 0x2;
private static final int ERROR_OVERFLOW = 0x4;
private static final int ERROR_ATTRIBUTION_CHAIN_TOO_LONG = 0x8;
- private static final int ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD = 0x10;
- private static final int ERROR_INVALID_ANNOTATION_ID = 0x20;
- private static final int ERROR_ANNOTATION_ID_TOO_LARGE = 0x40;
- private static final int ERROR_TOO_MANY_ANNOTATIONS = 0x80;
- private static final int ERROR_TOO_MANY_FIELDS = 0x100;
- private static final int ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL = 0x200;
+ private static final int ERROR_TOO_MANY_KEY_VALUE_PAIRS = 0x10;
+ private static final int ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD = 0x20;
+ private static final int ERROR_INVALID_ANNOTATION_ID = 0x40;
+ private static final int ERROR_ANNOTATION_ID_TOO_LARGE = 0x80;
+ private static final int ERROR_TOO_MANY_ANNOTATIONS = 0x100;
+ private static final int ERROR_TOO_MANY_FIELDS = 0x200;
+ private static final int ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL = 0x400;
// Size limits.
private static final int MAX_ANNOTATION_COUNT = 15;
private static final int MAX_ATTRIBUTION_NODES = 127;
private static final int MAX_NUM_ELEMENTS = 127;
+ private static final int MAX_KEY_VALUE_PAIRS = 127;
// Fixed positions.
private static final int POS_NUM_ELEMENTS = 1;
@@ -309,6 +318,72 @@ public final class StatsEvent {
}
/**
+ * Write KeyValuePairsAtom entries to this StatsEvent.
+ *
+ * @param intMap Integer key-value pairs.
+ * @param longMap Long key-value pairs.
+ * @param stringMap String key-value pairs.
+ * @param floatMap Float key-value pairs.
+ **/
+ @NonNull
+ public Builder writeKeyValuePairs(
+ @NonNull final SparseIntArray intMap,
+ @NonNull final SparseLongArray longMap,
+ @NonNull final SparseArray<String> stringMap,
+ @NonNull final SparseArray<Float> floatMap) {
+ final int intMapSize = intMap.size();
+ final int longMapSize = longMap.size();
+ final int stringMapSize = stringMap.size();
+ final int floatMapSize = floatMap.size();
+ final int totalCount = intMapSize + longMapSize + stringMapSize + floatMapSize;
+
+ if (totalCount > MAX_KEY_VALUE_PAIRS) {
+ mErrorMask |= ERROR_TOO_MANY_KEY_VALUE_PAIRS;
+ } else {
+ writeTypeId(TYPE_KEY_VALUE_PAIRS);
+ mPos += mBuffer.putByte(mPos, (byte) totalCount);
+
+ for (int i = 0; i < intMapSize; i++) {
+ final int key = intMap.keyAt(i);
+ final int value = intMap.valueAt(i);
+ mPos += mBuffer.putInt(mPos, key);
+ writeTypeId(TYPE_INT);
+ mPos += mBuffer.putInt(mPos, value);
+ }
+
+ for (int i = 0; i < longMapSize; i++) {
+ final int key = longMap.keyAt(i);
+ final long value = longMap.valueAt(i);
+ mPos += mBuffer.putInt(mPos, key);
+ writeTypeId(TYPE_LONG);
+ mPos += mBuffer.putLong(mPos, value);
+ }
+
+ for (int i = 0; i < stringMapSize; i++) {
+ final int key = stringMap.keyAt(i);
+ final String value = stringMap.valueAt(i);
+ mPos += mBuffer.putInt(mPos, key);
+ writeTypeId(TYPE_STRING);
+ final byte[] valueBytes = stringToBytes(value);
+ mPos += mBuffer.putInt(mPos, valueBytes.length);
+ mPos += mBuffer.putByteArray(mPos, valueBytes);
+ }
+
+ for (int i = 0; i < floatMapSize; i++) {
+ final int key = floatMap.keyAt(i);
+ final float value = floatMap.valueAt(i);
+ mPos += mBuffer.putInt(mPos, key);
+ writeTypeId(TYPE_FLOAT);
+ mPos += mBuffer.putFloat(mPos, value);
+ }
+
+ mNumElements++;
+ }
+
+ return this;
+ }
+
+ /**
* Write a boolean annotation for the last field written.
**/
@NonNull
@@ -379,7 +454,7 @@ public final class StatsEvent {
size = mPos;
}
- return new StatsEvent(mBuffer, size);
+ return new StatsEvent(mAtomId, mBuffer, size);
}
private void writeTypeId(final byte typeId) {
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 0175ba201dd1..5876b03476ce 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -16,6 +16,7 @@
package android.view;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -139,7 +140,7 @@ public class TextureView extends View {
*
* @param context The context to associate this view with.
*/
- public TextureView(Context context) {
+ public TextureView(@NonNull Context context) {
super(context);
}
@@ -149,7 +150,7 @@ public class TextureView extends View {
* @param context The context to associate this view with.
* @param attrs The attributes of the XML tag that is inflating the view.
*/
- public TextureView(Context context, AttributeSet attrs) {
+ public TextureView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@@ -162,7 +163,7 @@ public class TextureView extends View {
* reference to a style resource that supplies default values for
* the view. Can be 0 to not look for defaults.
*/
- public TextureView(Context context, AttributeSet attrs, int defStyleAttr) {
+ public TextureView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@@ -179,7 +180,8 @@ public class TextureView extends View {
* defStyleAttr is 0 or can not be found in the theme. Can be 0
* to not look for defaults.
*/
- public TextureView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ public TextureView(@NonNull Context context, @Nullable AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@@ -484,13 +486,13 @@ public class TextureView extends View {
* situations, make sure this texture view is not marked opaque.</p>
*
* @param transform The transform to apply to the content of
- * this view.
+ * this view. If null the transform will be set to identity.
*
* @see #getTransform(android.graphics.Matrix)
* @see #isOpaque()
* @see #setOpaque(boolean)
*/
- public void setTransform(Matrix transform) {
+ public void setTransform(@Nullable Matrix transform) {
mMatrix.set(transform);
mMatrixChanged = true;
invalidateParentIfNeeded();
@@ -507,7 +509,7 @@ public class TextureView extends View {
*
* @see #setTransform(android.graphics.Matrix)
*/
- public Matrix getTransform(Matrix transform) {
+ public @NonNull Matrix getTransform(@Nullable Matrix transform) {
if (transform == null) {
transform = new Matrix();
}
@@ -544,7 +546,7 @@ public class TextureView extends View {
* @see #getBitmap(android.graphics.Bitmap)
* @see #getBitmap(int, int)
*/
- public Bitmap getBitmap() {
+ public @Nullable Bitmap getBitmap() {
return getBitmap(getWidth(), getHeight());
}
@@ -571,7 +573,7 @@ public class TextureView extends View {
* @see #getBitmap(android.graphics.Bitmap)
* @see #getBitmap()
*/
- public Bitmap getBitmap(int width, int height) {
+ public @Nullable Bitmap getBitmap(int width, int height) {
if (isAvailable() && width > 0 && height > 0) {
return getBitmap(Bitmap.createBitmap(getResources().getDisplayMetrics(),
width, height, Bitmap.Config.ARGB_8888));
@@ -602,7 +604,7 @@ public class TextureView extends View {
* @throws IllegalStateException if the hardware rendering context cannot be
* acquired to capture the bitmap
*/
- public Bitmap getBitmap(Bitmap bitmap) {
+ public @NonNull Bitmap getBitmap(@NonNull Bitmap bitmap) {
if (bitmap != null && isAvailable()) {
applyUpdate();
applyTransformMatrix();
@@ -649,12 +651,13 @@ public class TextureView extends View {
* owned by another producer. For instance, if the TextureView is being used
* to render the camera's preview you cannot invoke this method.</p>
*
- * @return A Canvas used to draw into the surface.
+ * @return A Canvas used to draw into the surface, or null if the surface cannot be locked for
+ * drawing (see {@link #isAvailable()}).
*
* @see #lockCanvas(android.graphics.Rect)
* @see #unlockCanvasAndPost(android.graphics.Canvas)
*/
- public Canvas lockCanvas() {
+ public @Nullable Canvas lockCanvas() {
return lockCanvas(null);
}
@@ -669,15 +672,17 @@ public class TextureView extends View {
* already connected to an image producer (for instance: the camera,
* OpenGL, a media player, etc.)
*
- * @param dirty Area of the surface that will be modified.
+ * @param dirty Area of the surface that will be modified. If null the area of the entire
+ * surface is used.
- * @return A Canvas used to draw into the surface.
+ * @return A Canvas used to draw into the surface, or null if the surface cannot be locked for
+ * drawing (see {@link #isAvailable()}).
*
* @see #lockCanvas()
* @see #unlockCanvasAndPost(android.graphics.Canvas)
* @see #isAvailable()
*/
- public Canvas lockCanvas(Rect dirty) {
+ public @Nullable Canvas lockCanvas(@Nullable Rect dirty) {
if (!isAvailable()) return null;
if (mCanvas == null) {
@@ -705,7 +710,7 @@ public class TextureView extends View {
* @see #lockCanvas()
* @see #lockCanvas(android.graphics.Rect)
*/
- public void unlockCanvasAndPost(Canvas canvas) {
+ public void unlockCanvasAndPost(@NonNull Canvas canvas) {
if (mCanvas != null && canvas == mCanvas) {
canvas.restoreToCount(mSaveCount);
mSaveCount = 0;
@@ -723,7 +728,7 @@ public class TextureView extends View {
*
* @see #isAvailable()
*/
- public SurfaceTexture getSurfaceTexture() {
+ public @Nullable SurfaceTexture getSurfaceTexture() {
return mSurface;
}
@@ -742,7 +747,7 @@ public class TextureView extends View {
* @param surfaceTexture The {@link SurfaceTexture} that the view should use.
* @see SurfaceTexture#detachFromGLContext()
*/
- public void setSurfaceTexture(SurfaceTexture surfaceTexture) {
+ public void setSurfaceTexture(@NonNull SurfaceTexture surfaceTexture) {
if (surfaceTexture == null) {
throw new NullPointerException("surfaceTexture must not be null");
}
@@ -781,7 +786,7 @@ public class TextureView extends View {
* @see #setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener)
* @see SurfaceTextureListener
*/
- public SurfaceTextureListener getSurfaceTextureListener() {
+ public @Nullable SurfaceTextureListener getSurfaceTextureListener() {
return mListener;
}
@@ -792,25 +797,22 @@ public class TextureView extends View {
* @see #getSurfaceTextureListener()
* @see SurfaceTextureListener
*/
- public void setSurfaceTextureListener(SurfaceTextureListener listener) {
+ public void setSurfaceTextureListener(@Nullable SurfaceTextureListener listener) {
mListener = listener;
}
@UnsupportedAppUsage
private final SurfaceTexture.OnFrameAvailableListener mUpdateListener =
- new SurfaceTexture.OnFrameAvailableListener() {
- @Override
- public void onFrameAvailable(SurfaceTexture surfaceTexture) {
- updateLayer();
- invalidate();
- }
- };
+ surfaceTexture -> {
+ updateLayer();
+ invalidate();
+ };
/**
* This listener can be used to be notified when the surface texture
* associated with this texture view is available.
*/
- public static interface SurfaceTextureListener {
+ public interface SurfaceTextureListener {
/**
* Invoked when a {@link TextureView}'s SurfaceTexture is ready for use.
*
@@ -819,7 +821,7 @@ public class TextureView extends View {
* @param width The width of the surface
* @param height The height of the surface
*/
- public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height);
+ void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height);
/**
* Invoked when the {@link SurfaceTexture}'s buffers size changed.
@@ -829,7 +831,7 @@ public class TextureView extends View {
* @param width The new width of the surface
* @param height The new height of the surface
*/
- public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height);
+ void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height);
/**
* Invoked when the specified {@link SurfaceTexture} is about to be destroyed.
@@ -839,7 +841,7 @@ public class TextureView extends View {
*
* @param surface The surface about to be destroyed
*/
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surface);
+ boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface);
/**
* Invoked when the specified {@link SurfaceTexture} is updated through
@@ -847,7 +849,7 @@ public class TextureView extends View {
*
* @param surface The surface just updated
*/
- public void onSurfaceTextureUpdated(SurfaceTexture surface);
+ void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface);
}
@UnsupportedAppUsage
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1599afb358e0..412b0ca95680 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -493,7 +493,7 @@ import java.util.function.Predicate;
*
* <p>
* To initiate a layout, call {@link #requestLayout}. This method is typically
- * called by a view on itself when it believes that is can no longer fit within
+ * called by a view on itself when it believes that it can no longer fit within
* its current bounds.
* </p>
*
@@ -2836,7 +2836,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
- * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
+ * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph's text direction.
*
* Use with {@link #setTextAlignment(int)}
*/
@@ -2864,7 +2864,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
public static final int TEXT_ALIGNMENT_CENTER = 4;
/**
- * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
+ * Align to the start of the view, which is ALIGN_LEFT if the view's resolved
* layoutDirection is LTR, and ALIGN_RIGHT otherwise.
*
* Use with {@link #setTextAlignment(int)}
@@ -2872,7 +2872,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
public static final int TEXT_ALIGNMENT_VIEW_START = 5;
/**
- * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
+ * Align to the end of the view, which is ALIGN_RIGHT if the view's resolved
* layoutDirection is LTR, and ALIGN_LEFT otherwise.
*
* Use with {@link #setTextAlignment(int)}
@@ -3675,7 +3675,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* if the user swipes from the top of the screen.
* <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
* system gestures, such as swiping from the top of the screen. These transient system bars
- * will overlay app’s content, may have some degree of transparency, and will automatically
+ * will overlay app's content, may have some degree of transparency, and will automatically
* hide after a short timeout.
* </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
* {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
@@ -8727,7 +8727,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
structure.setContextClickable(true);
}
structure.setClassName(getAccessibilityClassName().toString());
- structure.setContentDescription(getContentDescription());
+ structure.setContentDescription(mContentDescription);
}
/**
@@ -9934,8 +9934,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
info.setImportantForAccessibility(isImportantForAccessibility());
info.setPackageName(mContext.getPackageName());
info.setClassName(getAccessibilityClassName());
- info.setStateDescription(getStateDescription());
- info.setContentDescription(getContentDescription());
+ info.setStateDescription(mStateDescription);
+ info.setContentDescription(mContentDescription);
info.setEnabled(isEnabled());
info.setClickable(isClickable());
@@ -10295,7 +10295,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * Gets the unique identifier of the window in which this View reseides.
+ * Gets the unique identifier of the window in which this View resides.
*
* @return The window accessibility id.
*
@@ -10318,7 +10318,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @see #setStateDescription(CharSequence)
*/
@ViewDebug.ExportedProperty(category = "accessibility")
- public final @Nullable CharSequence getStateDescription() {
+ public @Nullable CharSequence getStateDescription() {
return mStateDescription;
}
@@ -13724,7 +13724,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@UnsupportedAppUsage
public CharSequence getIterableTextForAccessibility() {
- return getContentDescription();
+ return mContentDescription;
}
/**
@@ -29514,9 +29514,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
stream.addProperty("text:textAlignment", getTextAlignment());
// accessibility
- CharSequence contentDescription = getContentDescription();
stream.addProperty("accessibility:contentDescription",
- contentDescription == null ? "" : contentDescription.toString());
+ mContentDescription == null ? "" : mContentDescription.toString());
+ stream.addProperty("accessibility:stateDescription",
+ mStateDescription == null ? "" : mStateDescription.toString());
stream.addProperty("accessibility:labelFor", getLabelFor());
stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
}
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 9e914d4e7d41..6a099d57145b 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -23,7 +23,6 @@ import android.app.AppGlobals;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.graphics.Point;
import android.os.Build;
import android.os.RemoteException;
import android.provider.Settings;
@@ -398,11 +397,7 @@ public class ViewConfiguration {
mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f);
// Size of the screen in bytes, in ARGB_8888 format
- final WindowManager win = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
- final Display display = win.getDefaultDisplay();
- final Point size = new Point();
- display.getRealSize(size);
- mMaximumDrawingCacheSize = 4 * size.x * size.y;
+ mMaximumDrawingCacheSize = 4 * metrics.heightPixels * metrics.widthPixels;
mOverscrollDistance = (int) (sizeAndDensity * OVERSCROLL_DISTANCE + 0.5f);
mOverflingDistance = (int) (sizeAndDensity * OVERFLING_DISTANCE + 0.5f);
@@ -842,6 +837,7 @@ public class ViewConfiguration {
* The maximum drawing cache size expressed in bytes.
*
* @return the maximum size of View's drawing cache expressed in bytes
+ *
*/
public int getScaledMaximumDrawingCacheSize() {
return mMaximumDrawingCacheSize;
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index f4f7d0b33fd1..6c6046f1876f 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -93,8 +93,9 @@ class WindowlessWindowManager implements IWindowSession {
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
InsetsState outInsetsState) {
final SurfaceControl.Builder b = new SurfaceControl.Builder(mSurfaceSession)
- .setParent(mRootSurface)
- .setName(attrs.getTitle().toString());
+ .setParent(mRootSurface)
+ .setFormat(attrs.format)
+ .setName(attrs.getTitle().toString());
final SurfaceControl sc = b.build();
synchronized (this) {
mStateForWindow.put(window.asBinder(), new State(sc, attrs));
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.aidl b/core/java/android/view/accessibility/AccessibilityNodeInfo.aidl
index 59175cebd773..dbc9903f6630 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.aidl
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.aidl
@@ -17,3 +17,4 @@
package android.view.accessibility;
parcelable AccessibilityNodeInfo;
+parcelable AccessibilityNodeInfo.AccessibilityAction;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 06e9d0dbf6d6..b33fdbbf8a96 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -3570,8 +3570,7 @@ public class AccessibilityNodeInfo implements Parcelable {
for (int i = 0; i < actionCount; i++) {
AccessibilityAction action = mActions.get(i);
if (!isDefaultStandardAction(action)) {
- parcel.writeInt(action.getId());
- parcel.writeCharSequence(action.getLabel());
+ action.writeToParcel(parcel, flags);
}
}
} else {
@@ -3777,8 +3776,8 @@ public class AccessibilityNodeInfo implements Parcelable {
addStandardActions(standardActions);
final int nonStandardActionCount = parcel.readInt();
for (int i = 0; i < nonStandardActionCount; i++) {
- final AccessibilityAction action = new AccessibilityAction(
- parcel.readInt(), parcel.readCharSequence());
+ final AccessibilityAction action =
+ AccessibilityAction.CREATOR.createFromParcel(parcel);
addActionUnchecked(action);
}
}
@@ -4177,7 +4176,7 @@ public class AccessibilityNodeInfo implements Parcelable {
* can discover the set of supported actions.
* </p>
*/
- public static final class AccessibilityAction {
+ public static final class AccessibilityAction implements Parcelable {
/** @hide */
public static final ArraySet<AccessibilityAction> sStandardActions = new ArraySet<>();
@@ -4654,6 +4653,38 @@ public class AccessibilityNodeInfo implements Parcelable {
public String toString() {
return "AccessibilityAction: " + getActionSymbolicName(mActionId) + " - " + mLabel;
}
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Write data into a parcel.
+ */
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeInt(mActionId);
+ out.writeCharSequence(mLabel);
+ }
+
+ public static final @NonNull Parcelable.Creator<AccessibilityAction> CREATOR =
+ new Parcelable.Creator<AccessibilityAction>() {
+ public AccessibilityAction createFromParcel(Parcel in) {
+ return new AccessibilityAction(in);
+ }
+
+ public AccessibilityAction[] newArray(int size) {
+ return new AccessibilityAction[size];
+ }
+ };
+
+ private AccessibilityAction(Parcel in) {
+ mActionId = in.readInt();
+ mLabel = in.readCharSequence();
+ }
}
/**
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index c877b9cec812..f5b074674454 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -127,7 +127,7 @@ public class AnimationUtils {
*
* @param context Application context used to access resources
* @param id The resource id of the animation to load
- * @return The animation object reference by the specified id
+ * @return The animation object referenced by the specified id
* @throws NotFoundException when the animation cannot be loaded
*/
public static Animation loadAnimation(Context context, @AnimRes int id)
@@ -208,7 +208,7 @@ public class AnimationUtils {
*
* @param context Application context used to access resources
* @param id The resource id of the animation to load
- * @return The animation object reference by the specified id
+ * @return The animation controller object referenced by the specified id
* @throws NotFoundException when the layout animation controller cannot be loaded
*/
public static LayoutAnimationController loadLayoutAnimation(Context context, @AnimRes int id)
@@ -331,7 +331,7 @@ public class AnimationUtils {
*
* @param context Application context used to access resources
* @param id The resource id of the animation to load
- * @return The animation object reference by the specified id
+ * @return The interpolator object referenced by the specified id
* @throws NotFoundException
*/
public static Interpolator loadInterpolator(Context context, @AnimRes @InterpolatorRes int id)
@@ -361,7 +361,7 @@ public class AnimationUtils {
*
* @param res The resources
* @param id The resource id of the animation to load
- * @return The interpolator object reference by the specified id
+ * @return The interpolator object referenced by the specified id
* @throws NotFoundException
* @hide
*/
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 3bbd3213409a..54446e1cf057 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -208,6 +208,10 @@ public final class AutofillManager {
public static final String EXTRA_RESTORE_SESSION_TOKEN =
"android.view.autofill.extra.RESTORE_SESSION_TOKEN";
+ /** @hide */
+ public static final String EXTRA_RESTORE_CROSS_ACTIVITY =
+ "android.view.autofill.extra.RESTORE_CROSS_ACTIVITY";
+
/**
* Internal extra used to pass a binder to the {@link IAugmentedAutofillManagerClient}.
*
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 7282008f7e3a..2895621f962a 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -328,6 +328,9 @@ public abstract class WebSettings {
* <p>
* The built-in mechanisms are the only currently supported zoom
* mechanisms, so it is recommended that this setting is always enabled.
+ * However, on-screen zoom controls are deprecated in Android (see
+ * {@link android.widget.ZoomButtonsController}) so it's recommended to
+ * disable {@link #setDisplayZoomControls}.
*
* @param enabled whether the WebView should use its built-in zoom mechanisms
*/
@@ -347,7 +350,9 @@ public abstract class WebSettings {
/**
* Sets whether the WebView should display on-screen zoom controls when
* using the built-in zoom mechanisms. See {@link #setBuiltInZoomControls}.
- * The default is {@code true}.
+ * The default is {@code true}. However, on-screen zoom controls are deprecated
+ * in Android (see {@link android.widget.ZoomButtonsController}) so it's
+ * recommended to set this to {@code false}.
*
* @param enabled whether the WebView should display on-screen zoom controls
*/
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 1cb114856a4a..3a197e2277bf 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -120,10 +120,6 @@ import java.util.function.Predicate;
* <a href="{@docRoot}training/improving-layouts/smooth-scrolling.html">
* Making ListView Scrolling Smooth</a> for more ways to ensure a smooth user experience.</p>
*
- * <p>For a more complete example of creating a custom adapter, see the
- * <a href="{@docRoot}samples/CustomChoiceList/index.html">
- * Custom Choice List</a> sample app.</p>
- *
* <p>To specify an action when a user clicks or taps on a single list item, see
* <a href="{@docRoot}guide/topics/ui/declaring-layout.html#HandlingUserSelections">
* Handling click events</a>.</p>
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 6b324a541c42..167010b89bef 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -73,7 +73,7 @@ import java.util.TreeSet;
*
* <p>This behavior has been preserved for apps that set <code>android:targetSdkVersion="17"</code>
* or older in their manifest's <code>uses-sdk</code> tag for compatibility. Apps targeting SDK
- * version 18 or newer will receive the correct behavior</p>
+ * version 18 or newer will receive the correct behavior.</p>
*
* <p>See the <a href="{@docRoot}guide/topics/ui/layout/relative.html">Relative
* Layout</a> guide.</p>
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 3ab0b0d2294b..99bf93e98cd1 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -31,19 +31,19 @@ interface IAppOpsService {
// be kept in sync with frameworks/native/libs/binder/include/binder/IAppOpsService.h
// and not be reordered
int checkOperation(int code, int uid, String packageName);
- int noteOperation(int code, int uid, String packageName, String featureId);
- int startOperation(IBinder token, int code, int uid, String packageName, String featureId,
- boolean startIfModeDefault);
+ int noteOperation(int code, int uid, String packageName, @nullable String featureId);
+ int startOperation(IBinder token, int code, int uid, String packageName,
+ @nullable String featureId, boolean startIfModeDefault);
@UnsupportedAppUsage
void finishOperation(IBinder token, int code, int uid, String packageName,
- String featureId);
+ @nullable String featureId);
void startWatchingMode(int op, String packageName, IAppOpsCallback callback);
void stopWatchingMode(IAppOpsCallback callback);
IBinder getToken(IBinder clientToken);
int permissionToOpCode(String permission);
int checkAudioOperation(int code, int usage, int uid, String packageName);
- void noteAsyncOp(String callingPackageName, int uid, String packageName, int opCode,
- String featureId, String message);
+ void noteAsyncOp(@nullable String callingPackageName, int uid, @nullable String packageName,
+ int opCode, @nullable String featureId, String message);
boolean shouldCollectNotes(int opCode);
void setCameraAudioRestriction(int mode);
// End of methods also called by native code.
diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java
index a587936ee571..0286aa69b063 100644
--- a/core/java/com/android/internal/app/ResolverListAdapter.java
+++ b/core/java/com/android/internal/app/ResolverListAdapter.java
@@ -634,8 +634,7 @@ public class ResolverListAdapter extends BaseAdapter {
subLabel = null;
}
- if (!TextUtils.equals(text2.getText(), subLabel)
- && !TextUtils.isEmpty(subLabel)) {
+ if (!TextUtils.equals(text2.getText(), subLabel)) {
text2.setVisibility(View.VISIBLE);
text2.setText(subLabel);
}
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 36a7a9c91ee4..58e80c7c104f 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -47,6 +47,20 @@ public final class SystemUiDeviceConfigFlags {
*/
public static final String NAS_MAX_SUGGESTIONS = "nas_max_suggestions";
+ // Flags related to screenshot intelligence
+
+ /**
+ * (bool) Whether to enable smart actions in screenshot notifications.
+ */
+ public static final String ENABLE_SCREENSHOT_NOTIFICATION_SMART_ACTIONS =
+ "enable_screenshot_notification_smart_actions";
+
+ /**
+ * (int) Timeout value in ms to get smart actions for screenshot notification.
+ */
+ public static final String SCREENSHOT_NOTIFICATION_SMART_ACTIONS_TIMEOUT_MS =
+ "screenshot_notification_smart_actions_timeout_ms";
+
// Flags related to controls
/**
diff --git a/core/java/com/android/internal/os/BaseCommand.java b/core/java/com/android/internal/os/BaseCommand.java
index 278f40660ee9..e1b8e6c2d7d1 100644
--- a/core/java/com/android/internal/os/BaseCommand.java
+++ b/core/java/com/android/internal/os/BaseCommand.java
@@ -18,14 +18,14 @@
package com.android.internal.os;
import android.annotation.UnsupportedAppUsage;
-import android.os.ShellCommand;
+import android.os.BasicShellCommandHandler;
import java.io.PrintStream;
public abstract class BaseCommand {
@UnsupportedAppUsage
- final protected ShellCommand mArgs = new ShellCommand() {
+ final protected BasicShellCommandHandler mArgs = new BasicShellCommandHandler() {
@Override public int onCommand(String cmd) {
return 0;
}
@@ -50,7 +50,7 @@ public abstract class BaseCommand {
}
mRawArgs = args;
- mArgs.init(null, null, null, null, args, null, 0);
+ mArgs.init(null, null, null, null, args, 0);
try {
onRun();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index d6b32b58ce64..f5bfe5cfecaf 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -12618,20 +12618,20 @@ public class BatteryStatsImpl extends BatteryStats {
txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
totalTxTimeMs += txTimeMs[i];
}
- s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
- s.setKernelActiveTimeMs(getMobileRadioActiveTime(rawRealTime, which) / 1000);
+ s.setLoggingDurationMillis(computeBatteryRealtime(rawRealTime, which) / 1000);
+ s.setKernelActiveTimeMillis(getMobileRadioActiveTime(rawRealTime, which) / 1000);
s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which));
s.setNumBytesTx(getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which));
s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which));
s.setNumBytesRx(getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which));
- s.setSleepTimeMs(sleepTimeMs);
- s.setIdleTimeMs(idleTimeMs);
- s.setRxTimeMs(rxTimeMs);
- s.setEnergyConsumedMaMs(energyConsumedMaMs);
- s.setTimeInRatMs(timeInRatMs);
- s.setTimeInRxSignalStrengthLevelMs(timeInRxSignalStrengthLevelMs);
- s.setTxTimeMs(txTimeMs);
- s.setMonitoredRailChargeConsumedMaMs(monitoredRailChargeConsumedMaMs);
+ s.setSleepTimeMillis(sleepTimeMs);
+ s.setIdleTimeMillis(idleTimeMs);
+ s.setRxTimeMillis(rxTimeMs);
+ s.setEnergyConsumedMaMillis(energyConsumedMaMs);
+ s.setTimeInRatMicros(timeInRatMs);
+ s.setTimeInRxSignalStrengthLevelMicros(timeInRxSignalStrengthLevelMs);
+ s.setTxTimeMillis(txTimeMs);
+ s.setMonitoredRailChargeConsumedMaMillis(monitoredRailChargeConsumedMaMs);
return s;
}
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 3ce3838a212e..f3de34be2e69 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -114,6 +114,13 @@ public final class Zygote {
*/
public static final int DEBUG_IGNORE_APP_SIGNAL_HANDLER = 1 << 17;
+ /**
+ * Disable runtime access to {@link android.annotation.TestApi} annotated members.
+ *
+ * <p>This only takes effect if Hidden API access restrictions are enabled as well.
+ */
+ public static final int DISABLE_TEST_API_ENFORCEMENT_POLICY = 1 << 18;
+
/** No external storage should be mounted. */
public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE;
/** Default external storage should be mounted. */
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 317469e58245..73f549a31bac 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -38,25 +38,6 @@ oneway interface IStatusBar
void showWirelessChargingAnimation(int batteryLevel);
- /**
- * Notifies System UI side of a visibility flag change on the specified display.
- *
- * @param displayId the id of the display to notify
- * @param vis the visibility flags except SYSTEM_UI_FLAG_LIGHT_STATUS_BAR which will be reported
- * separately in fullscreenStackVis and dockedStackVis
- * @param fullscreenStackVis the flags which only apply in the region of the fullscreen stack,
- * which is currently only SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
- * @param dockedStackVis the flags that only apply in the region of the docked stack, which is
- * currently only SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
- * @param mask which flags to change
- * @param fullscreenBounds the current bounds of the fullscreen stack, in screen coordinates
- * @param dockedBounds the current bounds of the docked stack, in screen coordinates
- * @param navbarColorManagedByIme {@code true} if navigation bar color is managed by IME.
- */
- void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, int dockedStackVis,
- int mask, in Rect fullscreenBounds, in Rect dockedBounds,
- boolean navbarColorManagedByIme);
-
void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive);
void setImeWindowStatus(int displayId, in IBinder token, int vis, int backDisposition,
boolean showImeSwitcher, boolean isMultiClientImeEnabled);
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index d703b86d6c8d..3f08710bb17f 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -77,7 +77,6 @@ interface IStatusBarService
void onNotificationSmartReplySent(in String key, in int replyIndex, in CharSequence reply,
in int notificationLocation, boolean modifiedBeforeSending);
void onNotificationSettingsViewed(String key);
- void setSystemUiVisibility(int displayId, int vis, int mask, String cause);
void onNotificationBubbleChanged(String key, boolean isBubble);
void grantInlineReplyUriPermission(String key, in Uri uri, in UserHandle user, String packageName);
void clearInlineReplyUriPermissions(String key);
diff --git a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
index 4c3f04b10892..9095f05543da 100644
--- a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
+++ b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
@@ -16,53 +16,50 @@
package com.android.internal.statusbar;
-import android.graphics.Rect;
+import android.annotation.NonNull;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
+import com.android.internal.view.AppearanceRegion;
+
/**
* An immutable data object to return a set of values from StatusBarManagerService to its clients.
*/
public final class RegisterStatusBarResult implements Parcelable {
public final ArrayMap<String, StatusBarIcon> mIcons;
- public final int mDisabledFlags1; // switch[0]
- public final int mSystemUiVisibility; // switch[1]
- public final int mImeWindowVis; // switch[3]
- public final int mImeBackDisposition; // switch[4]
- public final boolean mShowImeSwitcher; // switch[5]
- public final int mDisabledFlags2; // switch[6]
- public final int mFullscreenStackSysUiVisibility; // switch[7]
- public final int mDockedStackSysUiVisibility; // switch[8]
+ public final int mDisabledFlags1; // switch[0]
+ public final int mAppearance; // switch[1]
+ public final AppearanceRegion[] mAppearanceRegions; // switch[2]
+ public final int mImeWindowVis; // switch[3]
+ public final int mImeBackDisposition; // switch[4]
+ public final boolean mShowImeSwitcher; // switch[5]
+ public final int mDisabledFlags2; // switch[6]
public final IBinder mImeToken;
- public final Rect mFullscreenStackBounds;
- public final Rect mDockedStackBounds;
public final boolean mNavbarColorManagedByIme;
public final boolean mAppFullscreen;
public final boolean mAppImmersive;
+ public final int[] mTransientBarTypes;
public RegisterStatusBarResult(ArrayMap<String, StatusBarIcon> icons, int disabledFlags1,
- int systemUiVisibility, int imeWindowVis, int imeBackDisposition,
- boolean showImeSwitcher, int disabledFlags2, int fullscreenStackSysUiVisibility,
- int dockedStackSysUiVisibility, IBinder imeToken, Rect fullscreenStackBounds,
- Rect dockedStackBounds, boolean navbarColorManagedByIme, boolean appFullscreen,
- boolean appImmersive) {
+ int appearance, AppearanceRegion[] appearanceRegions, int imeWindowVis,
+ int imeBackDisposition, boolean showImeSwitcher, int disabledFlags2, IBinder imeToken,
+ boolean navbarColorManagedByIme, boolean appFullscreen, boolean appImmersive,
+ @NonNull int[] transientBarTypes) {
mIcons = new ArrayMap<>(icons);
mDisabledFlags1 = disabledFlags1;
- mSystemUiVisibility = systemUiVisibility;
+ mAppearance = appearance;
+ mAppearanceRegions = appearanceRegions;
mImeWindowVis = imeWindowVis;
mImeBackDisposition = imeBackDisposition;
mShowImeSwitcher = showImeSwitcher;
mDisabledFlags2 = disabledFlags2;
- mFullscreenStackSysUiVisibility = fullscreenStackSysUiVisibility;
- mDockedStackSysUiVisibility = dockedStackSysUiVisibility;
mImeToken = imeToken;
- mFullscreenStackBounds = fullscreenStackBounds;
- mDockedStackBounds = dockedStackBounds;
mNavbarColorManagedByIme = navbarColorManagedByIme;
mAppFullscreen = appFullscreen;
mAppImmersive = appImmersive;
+ mTransientBarTypes = transientBarTypes;
}
@Override
@@ -74,19 +71,17 @@ public final class RegisterStatusBarResult implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedArrayMap(mIcons, flags);
dest.writeInt(mDisabledFlags1);
- dest.writeInt(mSystemUiVisibility);
+ dest.writeInt(mAppearance);
+ dest.writeParcelableArray(mAppearanceRegions, 0);
dest.writeInt(mImeWindowVis);
dest.writeInt(mImeBackDisposition);
dest.writeBoolean(mShowImeSwitcher);
dest.writeInt(mDisabledFlags2);
- dest.writeInt(mFullscreenStackSysUiVisibility);
- dest.writeInt(mDockedStackSysUiVisibility);
dest.writeStrongBinder(mImeToken);
- dest.writeTypedObject(mFullscreenStackBounds, flags);
- dest.writeTypedObject(mDockedStackBounds, flags);
dest.writeBoolean(mNavbarColorManagedByIme);
dest.writeBoolean(mAppFullscreen);
dest.writeBoolean(mAppImmersive);
+ dest.writeIntArray(mTransientBarTypes);
}
/**
@@ -99,24 +94,22 @@ public final class RegisterStatusBarResult implements Parcelable {
final ArrayMap<String, StatusBarIcon> icons =
source.createTypedArrayMap(StatusBarIcon.CREATOR);
final int disabledFlags1 = source.readInt();
- final int systemUiVisibility = source.readInt();
+ final int appearance = source.readInt();
+ final AppearanceRegion[] appearanceRegions =
+ source.readParcelableArray(null, AppearanceRegion.class);
final int imeWindowVis = source.readInt();
final int imeBackDisposition = source.readInt();
final boolean showImeSwitcher = source.readBoolean();
final int disabledFlags2 = source.readInt();
- final int fullscreenStackSysUiVisibility = source.readInt();
- final int dockedStackSysUiVisibility = source.readInt();
final IBinder imeToken = source.readStrongBinder();
- final Rect fullscreenStackBounds = source.readTypedObject(Rect.CREATOR);
- final Rect dockedStackBounds = source.readTypedObject(Rect.CREATOR);
final boolean navbarColorManagedByIme = source.readBoolean();
final boolean appFullscreen = source.readBoolean();
final boolean appImmersive = source.readBoolean();
- return new RegisterStatusBarResult(icons, disabledFlags1, systemUiVisibility,
- imeWindowVis, imeBackDisposition, showImeSwitcher, disabledFlags2,
- fullscreenStackSysUiVisibility, dockedStackSysUiVisibility, imeToken,
- fullscreenStackBounds, dockedStackBounds, navbarColorManagedByIme,
- appFullscreen, appImmersive);
+ final int[] transientBarTypes = source.createIntArray();
+ return new RegisterStatusBarResult(icons, disabledFlags1, appearance,
+ appearanceRegions, imeWindowVis, imeBackDisposition, showImeSwitcher,
+ disabledFlags2, imeToken, navbarColorManagedByIme, appFullscreen,
+ appImmersive, transientBarTypes);
}
@Override
diff --git a/core/java/com/android/internal/util/CollectionUtils.java b/core/java/com/android/internal/util/CollectionUtils.java
index f9cf23b29a69..4165f202998c 100644
--- a/core/java/com/android/internal/util/CollectionUtils.java
+++ b/core/java/com/android/internal/util/CollectionUtils.java
@@ -231,6 +231,15 @@ public class CollectionUtils {
}
/**
+ * Returns whether there exists at least one element in the set for which
+ * condition {@code predicate} is true
+ */
+ public static <T> boolean any(@Nullable Set<T> items,
+ java.util.function.Predicate<T> predicate) {
+ return find(items, predicate) != null;
+ }
+
+ /**
* Returns the first element from the list for which
* condition {@code predicate} is true, or null if there is no such element
*/
@@ -245,6 +254,37 @@ public class CollectionUtils {
}
/**
+ * Returns the first element from the set for which
+ * condition {@code predicate} is true, or null if there is no such element
+ */
+ public static @Nullable <T> T find(@Nullable Set<T> cur,
+ java.util.function.Predicate<T> predicate) {
+ if (cur == null || predicate == null) return null;
+ int size = cur.size();
+ if (size == 0) return null;
+ try {
+ if (cur instanceof ArraySet) {
+ ArraySet<T> arraySet = (ArraySet<T>) cur;
+ for (int i = 0; i < size; i++) {
+ T item = arraySet.valueAt(i);
+ if (predicate.test(item)) {
+ return item;
+ }
+ }
+ } else {
+ for (T t : cur) {
+ if (predicate.test(t)) {
+ return t;
+ }
+ }
+ }
+ } catch (Exception e) {
+ throw ExceptionUtils.propagate(e);
+ }
+ return null;
+ }
+
+ /**
* Similar to {@link List#add}, but with support for list values of {@code null} and
* {@link Collections#emptyList}
*/
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index d9428c5bf1ca..30edc3721efb 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -246,6 +246,7 @@ cc_library_shared {
"libmediametrics",
"libmeminfo",
"libaudioclient",
+ "libaudiofoundation",
"libaudiopolicy",
"libusbhost",
"libpdfium",
@@ -258,6 +259,7 @@ cc_library_shared {
"libmemunreachable",
"libhidlbase",
"libvintf",
+ "libnativedisplay",
"libnativewindow",
"libdl",
"libdl_android",
@@ -437,6 +439,7 @@ cc_library_static {
],
shared_libs: [
"libandroidfw",
+ "libnativedisplay",
"libnativewindow",
"libgui",
"libpdfium",
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 686a91901b5f..6417b283f520 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -27,6 +27,7 @@
#include "core_jni_helpers.h"
#include <audiomanager/AudioManager.h>
+#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioSystem.h>
#include <media/AudioPolicy.h>
#include <media/MicrophoneInfo.h>
@@ -2015,9 +2016,10 @@ static jint android_media_AudioSystem_setUidDeviceAffinities(JNIEnv *env, jobjec
if (!env->IsInstanceOf(addrJobj, stringClass)) {
return (jint) AUDIO_JAVA_BAD_VALUE;
}
- String8 address = String8(env->GetStringUTFChars((jstring) addrJobj, NULL));
+ const char* address = env->GetStringUTFChars((jstring) addrJobj, NULL);
AudioDeviceTypeAddr dev = AudioDeviceTypeAddr(typesPtr[i], address);
deviceVector.add(dev);
+ env->ReleaseStringUTFChars((jstring) addrJobj, address);
}
env->ReleaseIntArrayElements(deviceTypes, typesPtr, 0);
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 49c5cade314f..ee6e8c487bad 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -207,7 +207,7 @@ void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int tid, jint
return;
}
- int res = SetTaskProfiles(tid, {get_sched_policy_name((SchedPolicy)grp)}, true) ? 0 : -1;
+ int res = SetTaskProfiles(tid, {get_sched_policy_profile_name((SchedPolicy)grp)}, true) ? 0 : -1;
if (res != NO_ERROR) {
signalExceptionForGroupError(env, -res, tid);
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 2f87debce978..b9d28e4ce8eb 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -100,7 +100,8 @@ message ActivityStackProto {
message TaskRecordProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
- optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1;
+ // To be removed soon.
+ optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1 [deprecated=true];
optional int32 id = 2;
repeated ActivityRecordProto activities = 3;
optional int32 stack_id = 4;
@@ -113,6 +114,7 @@ message TaskRecordProto {
optional .android.graphics.RectProto bounds = 11;
optional int32 min_width = 12;
optional int32 min_height = 13;
+ optional .com.android.server.wm.TaskProto task = 14;
}
message ActivityRecordProto {
diff --git a/core/proto/android/server/appwindowthumbnail.proto b/core/proto/android/server/windowcontainerthumbnail.proto
index f22cdc541158..9f8ea60ca122 100644
--- a/core/proto/android/server/appwindowthumbnail.proto
+++ b/core/proto/android/server/windowcontainerthumbnail.proto
@@ -23,9 +23,9 @@ package com.android.server.wm;
option java_multiple_files = true;
/**
- * Represents a {@link com.android.server.wm.AppWindowThumbnail} object.
+ * Represents a {@link com.android.server.wm.WindowContainerThumbnailProto} object.
*/
-message AppWindowThumbnailProto {
+message WindowContainerThumbnailProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
optional int32 width = 1;
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 69e67d154d27..c9a18296a292 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -20,7 +20,7 @@ import "frameworks/base/core/proto/android/app/statusbarmanager.proto";
import "frameworks/base/core/proto/android/content/activityinfo.proto";
import "frameworks/base/core/proto/android/content/configuration.proto";
import "frameworks/base/core/proto/android/graphics/rect.proto";
-import "frameworks/base/core/proto/android/server/appwindowthumbnail.proto";
+import "frameworks/base/core/proto/android/server/windowcontainerthumbnail.proto";
import "frameworks/base/core/proto/android/server/surfaceanimator.proto";
import "frameworks/base/core/proto/android/view/displaycutout.proto";
import "frameworks/base/core/proto/android/view/displayinfo.proto";
@@ -232,7 +232,7 @@ message AppWindowTokenProto {
optional bool last_surface_showing = 3;
optional bool is_waiting_for_transition_start = 4;
optional bool is_animating = 5;
- optional AppWindowThumbnailProto thumbnail = 6;
+ optional WindowContainerThumbnailProto thumbnail = 6;
optional bool fills_parent = 7;
optional bool app_stopped = 8;
optional bool hidden_requested = 9;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 66e84dc16781..b357b3ebb349 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2280,7 +2280,7 @@
types of interactions
@hide -->
<permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
- android:protectionLevel="signature|installer|telephony" />
+ android:protectionLevel="signature|installer|telephony|wifi" />
<!-- @SystemApi Allows an application to start its own activities, but on a different profile
associated with the user. For example, an application running on the main profile of a user
@@ -3553,7 +3553,7 @@
<!-- Allows an application to manage the companion devices.
@hide -->
<permission android:name="android.permission.MANAGE_COMPANION_DEVICES"
- android:protectionLevel="signature" />
+ android:protectionLevel="signature|wifi" />
<!-- @SystemApi Allows an application to use SurfaceFlinger's low level features.
<p>Not for use by third-party applications.
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 585c4bba4ba9..b39fa133173f 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4869,10 +4869,10 @@
<string name="confirm_battery_saver">OK</string>
<!-- [CHAR_LIMIT=NONE] Battery saver: Feature description, with a "learn more" link. -->
- <string name="battery_saver_description_with_learn_more">Battery Saver turns off or restricts background activity, some visual effects \u0026 other high-power features to extend battery life. <annotation id="url">Learn More</annotation></string>
+ <string name="battery_saver_description_with_learn_more">To extend battery life, Battery Saver:\n&#183;Turns on Dark theme\n&#183;Turns off or restricts background activity, some visual effects, and other features like \u201cHey Google\u201d\n\n<annotation id="url">Learn more</annotation></string>
<!-- [CHAR_LIMIT=NONE] Battery saver: Feature description, without a "learn more" link. -->
- <string name="battery_saver_description">Battery Saver turns off or restricts background activity, some visual effects \u0026 other high-power features to extend battery life.</string>
+ <string name="battery_saver_description">To extend battery life, Battery Saver:\n&#183;Turns on Dark theme\n&#183;Turns off or restricts background activity, some visual effects, and other features like \u201cHey Google\u201d</string>
<!-- [CHAR_LIMIT=NONE] Data saver: Feature description -->
<string name="data_saver_description">To help reduce data usage, Data Saver prevents some apps from sending or receiving data in the background. An app you’re currently using can access data, but may do so less frequently. This may mean, for example, that images don’t display until you tap them.</string>
diff --git a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
index 0be5009f85f0..9f68ef31c166 100644
--- a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
+++ b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
@@ -18,7 +18,6 @@ package com.android.internal.statusbar;
import static com.google.common.truth.Truth.assertThat;
-import android.graphics.Rect;
import android.os.Binder;
import android.os.Parcel;
import android.os.UserHandle;
@@ -27,6 +26,8 @@ import android.util.ArrayMap;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.internal.view.AppearanceRegion;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -47,19 +48,17 @@ public class RegisterStatusBarResultTest {
final RegisterStatusBarResult original = new RegisterStatusBarResult(iconMap,
0x2 /* disabledFlags1 */,
- 0x4 /* systemUiVisibility */,
+ 0x4 /* appearance */,
+ new AppearanceRegion[0] /* appearanceRegions */,
0x8 /* imeWindowVis */,
0x10 /* imeBackDisposition */,
false /* showImeSwitcher */,
0x20 /* disabledFlags2 */,
- 0x40 /* fullscreenStackSysUiVisibility */,
- 0x80 /* dockedStackSysUiVisibility */,
new Binder() /* imeToken */,
- new Rect(0x100, 0x200, 0x400, 0x800) /* fullscreenStackBounds */,
- new Rect(0x1000, 0x2000, 0x4000, 0x8000) /* dockedStackBounds */,
true /* navbarColorManagedByIme */,
true /* appFullscreen */,
- true /* appImmersive */);
+ true /* appImmersive */,
+ new int[0] /* transientBarTypes */);
final RegisterStatusBarResult copy = clone(original);
@@ -69,21 +68,17 @@ public class RegisterStatusBarResultTest {
.isEqualTo(original.mIcons.get(dumyIconKey).user);
assertThat(copy.mDisabledFlags1).isEqualTo(original.mDisabledFlags1);
- assertThat(copy.mSystemUiVisibility).isEqualTo(original.mSystemUiVisibility);
+ assertThat(copy.mAppearance).isEqualTo(original.mAppearance);
+ assertThat(copy.mAppearanceRegions).isEqualTo(original.mAppearanceRegions);
assertThat(copy.mImeWindowVis).isEqualTo(original.mImeWindowVis);
assertThat(copy.mImeBackDisposition).isEqualTo(original.mImeBackDisposition);
assertThat(copy.mShowImeSwitcher).isEqualTo(original.mShowImeSwitcher);
assertThat(copy.mDisabledFlags2).isEqualTo(original.mDisabledFlags2);
- assertThat(copy.mFullscreenStackSysUiVisibility)
- .isEqualTo(original.mFullscreenStackSysUiVisibility);
- assertThat(copy.mDockedStackSysUiVisibility)
- .isEqualTo(original.mDockedStackSysUiVisibility);
assertThat(copy.mImeToken).isSameAs(original.mImeToken);
- assertThat(copy.mFullscreenStackBounds).isEqualTo(original.mFullscreenStackBounds);
- assertThat(copy.mDockedStackBounds).isEqualTo(original.mDockedStackBounds);
assertThat(copy.mNavbarColorManagedByIme).isEqualTo(original.mNavbarColorManagedByIme);
assertThat(copy.mAppFullscreen).isEqualTo(original.mAppFullscreen);
assertThat(copy.mAppImmersive).isEqualTo(original.mAppImmersive);
+ assertThat(copy.mTransientBarTypes).isEqualTo(original.mTransientBarTypes);
}
private RegisterStatusBarResult clone(RegisterStatusBarResult original) {
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index a0215e185a4c..77b0dba67be5 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -365,7 +365,7 @@ applications that come with the platform
<permission name="android.permission.CHANGE_CONFIGURATION"/>
<permission name="android.permission.CONNECTIVITY_INTERNAL"/>
<permission name="android.permission.DUMP"/>
- <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ <permission name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
<permission name="android.permission.INTERNAL_SYSTEM_WINDOW"/>
<permission name="android.permission.LOCAL_MAC_ADDRESS"/>
<permission name="android.permission.MANAGE_USERS"/>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 1326952a5750..5b9b70346807 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -301,12 +301,6 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
- "-1483752006": {
- "message": " THUMBNAIL %s: CREATE",
- "level": "INFO",
- "group": "WM_SHOW_TRANSACTIONS",
- "at": "com\/android\/server\/wm\/AppWindowThumbnail.java"
- },
"-1471946192": {
"message": "Marking app token %s with replacing child windows.",
"level": "DEBUG",
@@ -1297,6 +1291,12 @@
"group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
"at": "com\/android\/server\/wm\/AppTransition.java"
},
+ "531242746": {
+ "message": " THUMBNAIL %s: CREATE",
+ "level": "INFO",
+ "group": "WM_SHOW_TRANSACTIONS",
+ "at": "com\/android\/server\/wm\/WindowContainerThumbnail.java"
+ },
"539077569": {
"message": "Clear freezing of %s force=%b",
"level": "VERBOSE",
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index b7316ab03618..109d8631284d 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1114,7 +1114,7 @@ public class Paint {
* Return the width for stroking.
* <p />
* A value of 0 strokes in hairline mode.
- * Hairlines always draws a single pixel independent of the canva's matrix.
+ * Hairlines always draws a single pixel independent of the canvas's matrix.
*
* @return the paint's stroke width, used whenever the paint's style is
* Stroke or StrokeAndFill.
@@ -1126,7 +1126,7 @@ public class Paint {
/**
* Set the width for stroking.
* Pass 0 to stroke in hairline mode.
- * Hairlines always draws a single pixel independent of the canva's matrix.
+ * Hairlines always draws a single pixel independent of the canvas's matrix.
*
* @param width set the paint's stroke width, used whenever the paint's
* style is Stroke or StrokeAndFill.
@@ -1958,8 +1958,8 @@ public class Paint {
* <code>
* Paint paint = new Paint();
* paint.setStartHyphenEdit(Paint.START_HYPHEN_EDIT_INSERT_HYPHEN);
- * paint.measureText("abc", 0, 3); // Returns the width of "‐abc"
- * Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "‐abc"
+ * paint.measureText("abc", 0, 3); // Returns the width of "-abc"
+ * Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "-abc"
* </code>
* </pre>
*
@@ -1985,8 +1985,8 @@ public class Paint {
* <code>
* Paint paint = new Paint();
* paint.setEndHyphenEdit(Paint.END_HYPHEN_EDIT_INSERT_HYPHEN);
- * paint.measureText("abc", 0, 3); // Returns the width of "abc‐"
- * Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "abc‐"
+ * paint.measureText("abc", 0, 3); // Returns the width of "abc-"
+ * Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "abc-"
* </code>
* </pre>
*
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 2041e7a46364..ecfaec22de59 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -90,6 +90,7 @@ cc_defaults {
"libvulkan",
"libui",
"libgui",
+ "libnativedisplay",
"libnativewindow",
"libprotobuf-cpp-lite",
"libft2",
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index a0d3ff995e78..41e9b4be6649 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -15,74 +15,21 @@
*/
#include <DeviceInfo.h>
-
-#include "Properties.h"
-
#include <gui/SurfaceComposerClient.h>
+#include <log/log.h>
#include <ui/GraphicTypes.h>
#include <mutex>
#include <thread>
-#include <log/log.h>
+#include "Properties.h"
namespace android {
namespace uirenderer {
-static constexpr android::DisplayInfo sDummyDisplay{
- 1080, // w
- 1920, // h
- 320.0, // xdpi
- 320.0, // ydpi
- 60.0, // fps
- 2.0, // density
- 0, // orientation
- false, // secure?
- 0, // appVsyncOffset
- 0, // presentationDeadline
- 1080, // viewportW
- 1920, // viewportH
-};
-
DeviceInfo* DeviceInfo::get() {
- static DeviceInfo sDeviceInfo;
- return &sDeviceInfo;
-}
-
-static DisplayInfo QueryDisplayInfo() {
- if (Properties::isolatedProcess) {
- return sDummyDisplay;
- }
-
- const sp<IBinder> token = SurfaceComposerClient::getInternalDisplayToken();
- LOG_ALWAYS_FATAL_IF(token == nullptr,
- "Failed to get display info because internal display is disconnected");
-
- DisplayInfo displayInfo;
- status_t status = SurfaceComposerClient::getDisplayInfo(token, &displayInfo);
- LOG_ALWAYS_FATAL_IF(status, "Failed to get display info, error %d", status);
- return displayInfo;
-}
-
-static float QueryMaxRefreshRate() {
- if (Properties::isolatedProcess) {
- return sDummyDisplay.fps;
- }
-
- const sp<IBinder> token = SurfaceComposerClient::getInternalDisplayToken();
- LOG_ALWAYS_FATAL_IF(token == nullptr,
- "Failed to get display info because internal display is disconnected");
-
- Vector<DisplayInfo> configs;
- configs.reserve(10);
- status_t status = SurfaceComposerClient::getDisplayConfigs(token, &configs);
- LOG_ALWAYS_FATAL_IF(status, "Failed to getDisplayConfigs, error %d", status);
- LOG_ALWAYS_FATAL_IF(configs.size() == 0, "getDisplayConfigs returned 0 configs?");
- float max = 0.0f;
- for (auto& info : configs) {
- max = std::max(max, info.fps);
- }
- return max;
+ static DeviceInfo sDeviceInfo;
+ return &sDeviceInfo;
}
static void queryWideColorGamutPreference(sk_sp<SkColorSpace>* colorSpace, SkColorType* colorType) {
@@ -123,14 +70,17 @@ static void queryWideColorGamutPreference(sk_sp<SkColorSpace>* colorSpace, SkCol
}
}
-DeviceInfo::DeviceInfo() : mMaxRefreshRate(QueryMaxRefreshRate()) {
+DeviceInfo::DeviceInfo() {
#if HWUI_NULL_GPU
mMaxTextureSize = NULL_GPU_MAX_TEXTURE_SIZE;
#else
mMaxTextureSize = -1;
#endif
- mDisplayInfo = QueryDisplayInfo();
- queryWideColorGamutPreference(&mWideColorSpace, &mWideColorType);
+ updateDisplayInfo();
+ queryWideColorGamutPreference(&mWideColorSpace, &mWideColorType);
+}
+DeviceInfo::~DeviceInfo() {
+ ADisplay_release(mDisplays);
}
int DeviceInfo::maxTextureSize() const {
@@ -143,7 +93,36 @@ void DeviceInfo::setMaxTextureSize(int maxTextureSize) {
}
void DeviceInfo::onDisplayConfigChanged() {
- mDisplayInfo = QueryDisplayInfo();
+ updateDisplayInfo();
+}
+
+void DeviceInfo::updateDisplayInfo() {
+ if (Properties::isolatedProcess) {
+ return;
+ }
+
+ if (mCurrentConfig == nullptr) {
+ mDisplaysSize = ADisplay_acquirePhysicalDisplays(&mDisplays);
+ LOG_ALWAYS_FATAL_IF(mDisplays == nullptr || mDisplaysSize <= 0,
+ "Failed to get physical displays: no connected display: %d!", mDisplaysSize);
+ for (size_t i = 0; i < mDisplaysSize; i++) {
+ ADisplayType type = ADisplay_getDisplayType(mDisplays[i]);
+ if (type == ADisplayType::DISPLAY_TYPE_INTERNAL) {
+ mPhysicalDisplayIndex = i;
+ break;
+ }
+ }
+ LOG_ALWAYS_FATAL_IF(mPhysicalDisplayIndex < 0, "Failed to find a connected physical display!");
+ mMaxRefreshRate = ADisplay_getMaxSupportedFps(mDisplays[mPhysicalDisplayIndex]);
+ }
+ status_t status = ADisplay_getCurrentConfig(mDisplays[mPhysicalDisplayIndex], &mCurrentConfig);
+ LOG_ALWAYS_FATAL_IF(status, "Failed to get display config, error %d", status);
+ mWidth = ADisplayConfig_getWidth(mCurrentConfig);
+ mHeight = ADisplayConfig_getHeight(mCurrentConfig);
+ mDensity = ADisplayConfig_getDensity(mCurrentConfig);
+ mRefreshRate = ADisplayConfig_getFps(mCurrentConfig);
+ mCompositorOffset = ADisplayConfig_getCompositorOffsetNanos(mCurrentConfig);
+ mAppOffset = ADisplayConfig_getAppVsyncOffsetNanos(mCurrentConfig);
}
} /* namespace uirenderer */
diff --git a/libs/hwui/DeviceInfo.h b/libs/hwui/DeviceInfo.h
index 0e3f11960ddc..34315830ed97 100644
--- a/libs/hwui/DeviceInfo.h
+++ b/libs/hwui/DeviceInfo.h
@@ -16,8 +16,8 @@
#ifndef DEVICEINFO_H
#define DEVICEINFO_H
+#include <apex/display.h>
#include <SkImageInfo.h>
-#include <ui/DisplayInfo.h>
#include "utils/Macros.h"
@@ -33,28 +33,44 @@ class DeviceInfo {
public:
static DeviceInfo* get();
+ static float getMaxRefreshRate() { return get()->mMaxRefreshRate; }
+ static int32_t getWidth() { return get()->mWidth; }
+ static int32_t getHeight() { return get()->mHeight; }
+ static float getDensity() { return get()->mDensity; }
+ static float getRefreshRate() { return get()->mRefreshRate; }
+ static int64_t getCompositorOffset() { return get()->mCompositorOffset; }
+ static int64_t getAppOffset() { return get()->mAppOffset; }
// this value is only valid after the GPU has been initialized and there is a valid graphics
// context or if you are using the HWUI_NULL_GPU
int maxTextureSize() const;
- const DisplayInfo& displayInfo() const { return mDisplayInfo; }
sk_sp<SkColorSpace> getWideColorSpace() const { return mWideColorSpace; }
SkColorType getWideColorType() const { return mWideColorType; }
- float getMaxRefreshRate() const { return mMaxRefreshRate; }
void onDisplayConfigChanged();
private:
friend class renderthread::RenderThread;
static void setMaxTextureSize(int maxTextureSize);
+ void updateDisplayInfo();
DeviceInfo();
+ ~DeviceInfo();
int mMaxTextureSize;
- DisplayInfo mDisplayInfo;
sk_sp<SkColorSpace> mWideColorSpace;
SkColorType mWideColorType;
- const float mMaxRefreshRate;
+ ADisplayConfig* mCurrentConfig = nullptr;
+ ADisplay** mDisplays = nullptr;
+ int mDisplaysSize = 0;
+ int mPhysicalDisplayIndex = -1;
+ float mMaxRefreshRate = 60.0;
+ int32_t mWidth = 1080;
+ int32_t mHeight = 1920;
+ float mDensity = 2.0;
+ float mRefreshRate = 60.0;
+ int64_t mCompositorOffset = 0;
+ int64_t mAppOffset = 0;
};
} /* namespace uirenderer */
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index eae3584465e4..10e7160e7069 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -16,8 +16,10 @@
#include "JankTracker.h"
+#include <cutils/ashmem.h>
#include <errno.h>
#include <inttypes.h>
+#include <log/log.h>
#include <statslog.h>
#include <sys/mman.h>
@@ -25,11 +27,9 @@
#include <cmath>
#include <cstdio>
#include <limits>
-
-#include <cutils/ashmem.h>
-#include <log/log.h>
#include <sstream>
+#include "DeviceInfo.h"
#include "Properties.h"
#include "utils/TimeUtils.h"
#include "utils/Trace.h"
@@ -79,11 +79,11 @@ static const int64_t EXEMPT_FRAMES_FLAGS = FrameInfoFlags::SurfaceCanvas;
// and filter it out of the frame profile data
static FrameInfoIndex sFrameStart = FrameInfoIndex::IntendedVsync;
-JankTracker::JankTracker(ProfileDataContainer* globalData, const DisplayInfo& displayInfo) {
+JankTracker::JankTracker(ProfileDataContainer* globalData) {
mGlobalData = globalData;
- nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1_s / displayInfo.fps);
- nsecs_t sfOffset = frameIntervalNanos - (displayInfo.presentationDeadline - 1_ms);
- nsecs_t offsetDelta = sfOffset - displayInfo.appVsyncOffset;
+ nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1_s / DeviceInfo::getRefreshRate());
+ nsecs_t sfOffset = DeviceInfo::getCompositorOffset();
+ nsecs_t offsetDelta = sfOffset - DeviceInfo::getAppOffset();
// There are two different offset cases. If the offsetDelta is positive
// and small, then the intention is to give apps extra time by leveraging
// pipelining between the UI & RT threads. If the offsetDelta is large or
diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h
index 08059268f03e..4460266276f9 100644
--- a/libs/hwui/JankTracker.h
+++ b/libs/hwui/JankTracker.h
@@ -23,7 +23,6 @@
#include "utils/RingBuffer.h"
#include <cutils/compiler.h>
-#include <ui/DisplayInfo.h>
#include <array>
#include <memory>
@@ -49,7 +48,7 @@ struct ProfileDataDescription {
// TODO: Replace DrawProfiler with this
class JankTracker {
public:
- explicit JankTracker(ProfileDataContainer* globalData, const DisplayInfo& displayInfo);
+ explicit JankTracker(ProfileDataContainer* globalData);
void setDescription(JankTrackerType type, const std::string&& name) {
mDescription.type = type;
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 4e7df88b8095..446e81e65bb8 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -16,7 +16,6 @@
#include "Properties.h"
#include "Debug.h"
-#include "DeviceInfo.h"
#ifdef __ANDROID__
#include "HWUIProperties.sysprop.h"
#endif
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index e9794489f171..24f6035b6708 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -16,7 +16,10 @@
#pragma once
+#ifdef __ANDROID__ // Layoutlib does not support device info
#include "DeviceInfo.h"
+#endif // __ANDROID__
+
#include "Outline.h"
#include "Rect.h"
#include "RevealClip.h"
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index b366a80f918a..eaed46c44e5d 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -16,6 +16,7 @@
#include "CacheManager.h"
+#include "DeviceInfo.h"
#include "Layer.h"
#include "Properties.h"
#include "RenderThread.h"
@@ -42,8 +43,8 @@ namespace renderthread {
#define SURFACE_SIZE_MULTIPLIER (5.0f * 4.0f)
#define BACKGROUND_RETENTION_PERCENTAGE (0.5f)
-CacheManager::CacheManager(const DisplayInfo& display)
- : mMaxSurfaceArea(display.w * display.h)
+CacheManager::CacheManager()
+ : mMaxSurfaceArea(DeviceInfo::getWidth() * DeviceInfo::getHeight())
, mMaxResourceBytes(mMaxSurfaceArea * SURFACE_SIZE_MULTIPLIER)
, mBackgroundResourceBytes(mMaxResourceBytes * BACKGROUND_RETENTION_PERCENTAGE)
// This sets the maximum size for a single texture atlas in the GPU font cache. If
@@ -52,9 +53,9 @@ CacheManager::CacheManager(const DisplayInfo& display)
, mMaxGpuFontAtlasBytes(GrNextSizePow2(mMaxSurfaceArea))
// This sets the maximum size of the CPU font cache to be at least the same size as the
// total number of GPU font caches (i.e. 4 separate GPU atlases).
- , mMaxCpuFontCacheBytes(std::max(mMaxGpuFontAtlasBytes*4, SkGraphics::GetFontCacheLimit()))
+ , mMaxCpuFontCacheBytes(
+ std::max(mMaxGpuFontAtlasBytes * 4, SkGraphics::GetFontCacheLimit()))
, mBackgroundCpuFontCacheBytes(mMaxCpuFontCacheBytes * BACKGROUND_RETENTION_PERCENTAGE) {
-
SkGraphics::SetFontCacheLimit(mMaxCpuFontCacheBytes);
}
diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h
index 857710babf0c..968251e9f467 100644
--- a/libs/hwui/renderthread/CacheManager.h
+++ b/libs/hwui/renderthread/CacheManager.h
@@ -21,7 +21,6 @@
#include <GrContext.h>
#endif
#include <SkSurface.h>
-#include <ui/DisplayInfo.h>
#include <utils/String8.h>
#include <vector>
@@ -55,7 +54,7 @@ public:
private:
friend class RenderThread;
- explicit CacheManager(const DisplayInfo& display);
+ explicit CacheManager();
#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
void reset(sk_sp<GrContext> grContext);
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 15e0c8d0a266..826a8ea09d7e 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -102,13 +102,13 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode*
, mGenerationID(0)
, mOpaque(!translucent)
, mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
- , mJankTracker(&thread.globalProfileData(), DeviceInfo::get()->displayInfo())
+ , mJankTracker(&thread.globalProfileData())
, mProfiler(mJankTracker.frames(), thread.timeLord().frameIntervalNanos())
, mContentDrawBounds(0, 0, 0, 0)
, mRenderPipeline(std::move(renderPipeline)) {
rootRenderNode->makeRoot();
mRenderNodes.emplace_back(rootRenderNode);
- mProfiler.setDensity(DeviceInfo::get()->displayInfo().density);
+ mProfiler.setDensity(DeviceInfo::getDensity());
setRenderAheadDepth(Properties::defaultRenderAhead);
}
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index ee1a7ce19e82..a446858ca565 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -179,12 +179,11 @@ void RenderThread::initThreadLocals() {
mEglManager = new EglManager();
mRenderState = new RenderState(*this);
mVkManager = new VulkanManager();
- mCacheManager = new CacheManager(DeviceInfo::get()->displayInfo());
+ mCacheManager = new CacheManager();
}
void RenderThread::setupFrameInterval() {
- auto& displayInfo = DeviceInfo::get()->displayInfo();
- nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1000000000 / displayInfo.fps);
+ nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1000000000 / DeviceInfo::getRefreshRate());
mTimeLord.setFrameInterval(frameIntervalNanos);
mDispatchFrameDelay = static_cast<nsecs_t>(frameIntervalNanos * .25f);
}
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 5aa1af32094f..bdd80721c4f3 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -29,7 +29,6 @@
#include <GrContext.h>
#include <SkBitmap.h>
#include <cutils/compiler.h>
-#include <ui/DisplayInfo.h>
#include <utils/Looper.h>
#include <utils/Thread.h>
diff --git a/libs/hwui/tests/unit/CacheManagerTests.cpp b/libs/hwui/tests/unit/CacheManagerTests.cpp
index 3f1ef93c878c..c83a3c88cbdd 100644
--- a/libs/hwui/tests/unit/CacheManagerTests.cpp
+++ b/libs/hwui/tests/unit/CacheManagerTests.cpp
@@ -33,7 +33,8 @@ static size_t getCacheUsage(GrContext* grContext) {
}
RENDERTHREAD_SKIA_PIPELINE_TEST(CacheManager, trimMemory) {
- DisplayInfo displayInfo = DeviceInfo::get()->displayInfo();
+ int32_t width = DeviceInfo::get()->getWidth();
+ int32_t height = DeviceInfo::get()->getHeight();
GrContext* grContext = renderThread.getGrContext();
ASSERT_TRUE(grContext != nullptr);
@@ -42,7 +43,7 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(CacheManager, trimMemory) {
std::vector<sk_sp<SkSurface>> surfaces;
while (getCacheUsage(grContext) <= renderThread.cacheManager().getBackgroundCacheSize()) {
- SkImageInfo info = SkImageInfo::MakeA8(displayInfo.w, displayInfo.h);
+ SkImageInfo info = SkImageInfo::MakeA8(width, height);
sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(grContext, SkBudgeted::kYes, info);
surface->getCanvas()->drawColor(SK_AlphaTRANSPARENT);
@@ -52,8 +53,7 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(CacheManager, trimMemory) {
}
// create an image and pin it so that we have something with a unique key in the cache
- sk_sp<Bitmap> bitmap =
- Bitmap::allocateHeapBitmap(SkImageInfo::MakeA8(displayInfo.w, displayInfo.h));
+ sk_sp<Bitmap> bitmap = Bitmap::allocateHeapBitmap(SkImageInfo::MakeA8(width, height));
sk_sp<SkImage> image = bitmap->makeImage();
ASSERT_TRUE(SkImage_pinAsTexture(image.get(), grContext));
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index b7dd543680dc..c48f6e83ff20 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1890,7 +1890,7 @@ public class LocationManager {
@Deprecated
@RequiresPermission(ACCESS_FINE_LOCATION)
public boolean registerGnssStatusCallback(@NonNull GnssStatus.Callback callback) {
- return registerGnssStatusCallback(callback, null);
+ return registerGnssStatusCallback(Runnable::run, callback);
}
/**
@@ -1985,7 +1985,7 @@ public class LocationManager {
@Deprecated
@RequiresPermission(ACCESS_FINE_LOCATION)
public boolean addNmeaListener(@NonNull OnNmeaMessageListener listener) {
- return addNmeaListener(listener, null);
+ return addNmeaListener(Runnable::run, listener);
}
/**
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index 3abd2c2144e1..ca8f2ac82e94 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -505,6 +505,23 @@ public final class LocationRequest implements Parcelable {
}
/**
+ * Returns the realtime at which this request expires, taking into account both
+ * {@link #setExpireAt(long)} and {@link #setExpireIn(long)} relative to the given realtime.
+ *
+ * @hide
+ */
+ public long getExpirationRealtimeMs(long startRealtimeMs) {
+ long expirationRealtimeMs;
+ // Check for > Long.MAX_VALUE overflow (elapsedRealtime > 0):
+ if (mExpireIn > Long.MAX_VALUE - startRealtimeMs) {
+ expirationRealtimeMs = Long.MAX_VALUE;
+ } else {
+ expirationRealtimeMs = startRealtimeMs + mExpireIn;
+ }
+ return Math.min(expirationRealtimeMs, mExpireAt);
+ }
+
+ /**
* Set the number of location updates.
*
* <p>By default locations are continuously updated until the request is explicitly
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 70a343f4de01..7ba122baeca1 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -395,7 +395,7 @@ public abstract class Image implements AutoCloseable {
* <p>The row stride for this color plane, in bytes.</p>
*
* <p>This is the distance between the start of two consecutive rows of
- * pixels in the image. Note that row stried is undefined for some formats
+ * pixels in the image. Note that row stride is undefined for some formats
* such as
* {@link android.graphics.ImageFormat#RAW_PRIVATE RAW_PRIVATE},
* and calling getRowStride on images of these formats will
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index ce18ab3b3c83..cb6c126bc6b1 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -18,10 +18,14 @@ package android.media;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.content.Context;
import android.content.Intent;
+import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
@@ -30,6 +34,7 @@ import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import java.lang.annotation.Retention;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -40,12 +45,40 @@ import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
-
/**
* A new Media Router
* @hide
*/
public class MediaRouter2 {
+
+ /** @hide */
+ @Retention(SOURCE)
+ @IntDef(value = {
+ SELECT_REASON_UNKNOWN,
+ SELECT_REASON_USER_SELECTED,
+ SELECT_REASON_FALLBACK})
+ public @interface SelectReason {}
+
+ /**
+ * Passed to {@link Callback#onRouteSelected(MediaRoute2Info, int, Bundle)} when the reason
+ * the route was selected is unknown.
+ */
+ public static final int SELECT_REASON_UNKNOWN = 0;
+
+ /**
+ * Passed to {@link Callback#onRouteSelected(MediaRoute2Info, int, Bundle)} when the route
+ * is selected in response to a user's request. For example, when a user has selected
+ * a different device to play media to.
+ */
+ public static final int SELECT_REASON_USER_SELECTED = 1;
+
+ /**
+ * Passed to {@link Callback#onRouteSelected(MediaRoute2Info, int, Bundle)} when the route
+ * is selected as a fallback route. For example, when Wi-Fi is disconnected, the device speaker
+ * may be selected as a fallback route.
+ */
+ public static final int SELECT_REASON_FALLBACK = 2;
+
private static final String TAG = "MR2";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final Object sLock = new Object();
@@ -457,10 +490,31 @@ public class MediaRouter2 {
public void onRoutesRemoved(@NonNull List<MediaRoute2Info> routes) {}
/**
- * Called when routes are changed.
+ * Called when routes are changed. For example, it is called when the route's name
+ * or volume have been changed.
+ *
+ * TODO: Write here what the developers should do when this method is called.
+ * How they can find the exact point how a route is changed?
+ * It can be a volume, name, client package name, ....
+ *
* @param routes the list of routes that have been changed. It's never empty.
*/
public void onRoutesChanged(@NonNull List<MediaRoute2Info> routes) {}
+
+ // TODO: Make this callback be called when we add requestSelectRoute().
+ /**
+ * Called when a route is selected. Exactly one route can be selected at a time.
+ * @param route the selected route.
+ * @param reason the reason why the route is selected.
+ * @param connectionHints An optional bundle of provider-specific arguments which may be
+ * used to control the selected route. Can be empty.
+ * @see #SELECT_REASON_UNKNOWN
+ * @see #SELECT_REASON_USER_SELECTED
+ * @see #SELECT_REASON_FALLBACK
+ * @see #getSelectedRoute()
+ */
+ public void onRouteSelected(@NonNull MediaRoute2Info route, @SelectReason int reason,
+ @NonNull Bundle connectionHints) {}
}
final class CallbackRecord {
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index d1c171a2d7df..4ed8f423d6c9 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -16,6 +16,11 @@
package android.media.tv.tuner;
+import android.annotation.Nullable;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
import java.util.List;
/**
@@ -34,8 +39,9 @@ public final class Tuner implements AutoCloseable {
nativeInit();
}
- private FrontendCallback mFrontendCallback;
private List<Integer> mFrontendIds;
+ private Frontend mFrontend;
+ private EventHandler mHandler;
public Tuner() {
nativeSetup();
@@ -80,11 +86,66 @@ public final class Tuner implements AutoCloseable {
void onEvent(int frontendEventType);
}
- protected static class Frontend {
- int mId;
+ @Nullable
+ private EventHandler createEventHandler() {
+ Looper looper;
+ if ((looper = Looper.myLooper()) != null) {
+ return new EventHandler(looper);
+ } else if ((looper = Looper.getMainLooper()) != null) {
+ return new EventHandler(looper);
+ }
+ return null;
+ }
+
+ private class EventHandler extends Handler {
+ private EventHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_ON_FRONTEND_EVENT:
+ if (mFrontend != null && mFrontend.mCallback != null) {
+ mFrontend.mCallback.onEvent(msg.arg1);
+ }
+ break;
+ default:
+ // fall through
+ }
+ }
+ }
+
+ protected class Frontend {
+ private int mId;
+ private FrontendCallback mCallback;
+
private Frontend(int id) {
mId = id;
}
+
+ public void setCallback(@Nullable FrontendCallback callback, @Nullable Handler handler) {
+ mCallback = callback;
+
+ if (mCallback == null) {
+ return;
+ }
+
+ if (handler == null) {
+ // use default looper if handler is null
+ if (mHandler == null) {
+ mHandler = createEventHandler();
+ }
+ return;
+ }
+
+ Looper looper = handler.getLooper();
+ if (mHandler != null && mHandler.getLooper() == looper) {
+ // the same looper. reuse mHandler
+ return;
+ }
+ mHandler = new EventHandler(looper);
+ }
}
private List<Integer> getFrontendIds() {
@@ -94,12 +155,19 @@ public final class Tuner implements AutoCloseable {
private Frontend openFrontendById(int id) {
if (mFrontendIds == null) {
- getFrontendIds();
+ mFrontendIds = getFrontendIds();
}
if (!mFrontendIds.contains(id)) {
return null;
}
- return nativeOpenFrontendById(id);
+ mFrontend = nativeOpenFrontendById(id);
+ return mFrontend;
+ }
+
+ private void onFrontendEvent(int eventType) {
+ if (mHandler != null) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_FRONTEND_EVENT, eventType, 0));
+ }
}
protected class Filter {
diff --git a/media/jni/android_media_MediaCrypto.cpp b/media/jni/android_media_MediaCrypto.cpp
index 2d9051f5230d..517672ee6127 100644
--- a/media/jni/android_media_MediaCrypto.cpp
+++ b/media/jni/android_media_MediaCrypto.cpp
@@ -24,11 +24,10 @@
#include "jni.h"
#include <nativehelper/JNIHelp.h>
-#include <binder/IServiceManager.h>
#include <cutils/properties.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <mediadrm/DrmUtils.h>
#include <mediadrm/ICrypto.h>
-#include <mediadrm/IMediaDrmService.h>
namespace android {
@@ -64,20 +63,7 @@ JCrypto::~JCrypto() {
// static
sp<ICrypto> JCrypto::MakeCrypto() {
- sp<IServiceManager> sm = defaultServiceManager();
-
- sp<IBinder> binder = sm->getService(String16("media.drm"));
- sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
- if (service == NULL) {
- return NULL;
- }
-
- sp<ICrypto> crypto = service->makeCrypto();
- if (crypto == NULL || (crypto->initCheck() != OK && crypto->initCheck() != NO_INIT)) {
- return NULL;
- }
-
- return crypto;
+ return DrmUtils::MakeCrypto();
}
// static
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index f412161f418a..8f844d48df6d 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -27,14 +27,13 @@
#include "jni.h"
#include <nativehelper/JNIHelp.h>
-#include <binder/IServiceManager.h>
#include <binder/Parcel.h>
#include <binder/PersistableBundle.h>
#include <cutils/properties.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaErrors.h>
+#include <mediadrm/DrmUtils.h>
#include <mediadrm/IDrm.h>
-#include <mediadrm/IMediaDrmService.h>
using ::android::os::PersistableBundle;
@@ -486,20 +485,7 @@ JDrm::~JDrm() {
// static
sp<IDrm> JDrm::MakeDrm() {
- sp<IServiceManager> sm = defaultServiceManager();
-
- sp<IBinder> binder = sm->getService(String16("media.drm"));
- sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
- if (service == NULL) {
- return NULL;
- }
-
- sp<IDrm> drm = service->makeDrm();
- if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) {
- return NULL;
- }
-
- return drm;
+ return DrmUtils::MakeDrm();
}
// static
@@ -537,6 +523,40 @@ void JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj)
}
}
+void JDrm::sendEvent(
+ DrmPlugin::EventType eventType,
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ const hardware::hidl_vec<uint8_t> &data) {
+ Parcel obj;
+ DrmUtils::WriteByteArray(obj, sessionId);
+ DrmUtils::WriteByteArray(obj, data);
+ notify(eventType, 0, &obj);
+}
+
+void JDrm::sendExpirationUpdate(
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ int64_t expiryTimeInMS) {
+ Parcel obj;
+ DrmUtils::WriteExpirationUpdateToParcel(obj, sessionId, expiryTimeInMS);
+ notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
+}
+
+void JDrm::sendKeysChange(
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ const std::vector<DrmKeyStatus> &keyStatusList,
+ bool hasNewUsableKey) {
+ Parcel obj;
+ DrmUtils::WriteKeysChange(obj, sessionId, keyStatusList, hasNewUsableKey);
+ notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
+}
+
+void JDrm::sendSessionLostState(
+ const hardware::hidl_vec<uint8_t> &sessionId) {
+ Parcel obj;
+ DrmUtils::WriteByteArray(obj, sessionId);
+ notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &obj);
+}
+
void JDrm::disconnect() {
if (mDrm != NULL) {
mDrm->destroyPlugin();
diff --git a/media/jni/android_media_MediaDrm.h b/media/jni/android_media_MediaDrm.h
index 684069b0120a..37d9e079d857 100644
--- a/media/jni/android_media_MediaDrm.h
+++ b/media/jni/android_media_MediaDrm.h
@@ -21,6 +21,8 @@
#include <media/stagefright/foundation/ABase.h>
#include <mediadrm/IDrm.h>
+#include <mediadrm/IDrmClient.h>
+#include <hidl/HidlSupport.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -44,7 +46,23 @@ struct JDrm : public BnDrmClient {
status_t initCheck() const;
sp<IDrm> getDrm() { return mDrm; }
- void notify(DrmPlugin::EventType, int extra, const Parcel *obj);
+ void sendEvent(
+ DrmPlugin::EventType eventType,
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ const hardware::hidl_vec<uint8_t> &data) override;
+
+ void sendExpirationUpdate(
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ int64_t expiryTimeInMS) override;
+
+ void sendKeysChange(
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ const std::vector<DrmKeyStatus> &keyStatusList,
+ bool hasNewUsableKey) override;
+
+ void sendSessionLostState(
+ const hardware::hidl_vec<uint8_t> &sessionId) override;
+
status_t setListener(const sp<DrmListener>& listener);
void disconnect();
@@ -63,6 +81,8 @@ private:
static sp<IDrm> MakeDrm();
static sp<IDrm> MakeDrm(const uint8_t uuid[16], const String8 &appPackageName);
+ void notify(DrmPlugin::EventType, int extra, const Parcel *obj);
+
DISALLOW_EVIL_CONSTRUCTORS(JDrm);
};
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 9e96b74dd471..f8150972a413 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -36,6 +36,7 @@ struct fields_t {
jfieldID context;
jmethodID frontendInitID;
jmethodID filterInitID;
+ jmethodID onFrontendEventID;
};
static fields_t gFields;
@@ -52,7 +53,32 @@ Return<void> FilterCallback::onFilterStatus(const DemuxFilterStatus /*status*/)
return Void();
}
+/////////////// FrontendCallback ///////////////////////
+
+FrontendCallback::FrontendCallback(jweak tunerObj, FrontendId id) : mObject(tunerObj), mId(id) {}
+
+Return<void> FrontendCallback::onEvent(FrontendEventType frontendEventType) {
+ ALOGD("FrontendCallback::onEvent, type=%d", frontendEventType);
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(
+ mObject,
+ gFields.onFrontendEventID,
+ (jint)frontendEventType);
+ return Void();
+}
+Return<void> FrontendCallback::onDiseqcMessage(const hidl_vec<uint8_t>& /*diseqcMessage*/) {
+ ALOGD("FrontendCallback::onDiseqcMessage");
+ return Void();
+}
+
+Return<void> FrontendCallback::onScanMessage(
+ FrontendScanMessageType type, const FrontendScanMessage& /*message*/) {
+ ALOGD("FrontendCallback::onScanMessage, type=%d", type);
+ return Void();
+}
+
/////////////// Tuner ///////////////////////
+
sp<ITuner> JTuner::mTuner;
JTuner::JTuner(JNIEnv *env, jobject thiz)
@@ -89,11 +115,10 @@ sp<ITuner> JTuner::getTunerService() {
jobject JTuner::getFrontendIds() {
ALOGD("JTuner::getFrontendIds()");
- hidl_vec<FrontendId> feIds;
mTuner->getFrontendIds([&](Result, const hidl_vec<FrontendId>& frontendIds) {
- feIds = frontendIds;
+ mFeIds = frontendIds;
});
- if (feIds.size() == 0) {
+ if (mFeIds.size() == 0) {
ALOGW("Frontend isn't available");
return NULL;
}
@@ -106,21 +131,25 @@ jobject JTuner::getFrontendIds() {
jclass integerClazz = env->FindClass("java/lang/Integer");
jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V");
- for (int i=0; i < feIds.size(); i++) {
- jobject idObj = env->NewObject(integerClazz, intInit, feIds[i]);
+ for (int i=0; i < mFeIds.size(); i++) {
+ jobject idObj = env->NewObject(integerClazz, intInit, mFeIds[i]);
env->CallBooleanMethod(obj, arrayListAdd, idObj);
}
return obj;
}
jobject JTuner::openFrontendById(int id) {
+ sp<IFrontend> fe;
mTuner->openFrontendById(id, [&](Result, const sp<IFrontend>& frontend) {
- mFe = frontend;
+ fe = frontend;
});
- if (mFe == nullptr) {
+ if (fe == nullptr) {
ALOGE("Failed to open frontend");
return NULL;
}
+ mFe = fe;
+ sp<FrontendCallback> feCb = new FrontendCallback(mObject, id);
+ fe->setCallback(feCb);
jint jId = (jint) id;
JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -128,6 +157,7 @@ jobject JTuner::openFrontendById(int id) {
return env->NewObject(
env->FindClass("android/media/tv/tuner/Tuner$Frontend"),
gFields.frontendInitID,
+ mObject,
(jint) jId);
}
@@ -210,8 +240,11 @@ static void android_media_tv_Tuner_native_init(JNIEnv *env) {
gFields.context = env->GetFieldID(clazz, "mNativeContext", "J");
CHECK(gFields.context != NULL);
+ gFields.onFrontendEventID = env->GetMethodID(clazz, "onFrontendEvent", "(I)V");
+
jclass frontendClazz = env->FindClass("android/media/tv/tuner/Tuner$Frontend");
- gFields.frontendInitID = env->GetMethodID(frontendClazz, "<init>", "(I)V");
+ gFields.frontendInitID =
+ env->GetMethodID(frontendClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
jclass filterClazz = env->FindClass("android/media/tv/tuner/Tuner$Filter");
gFields.filterInitID =
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index b23b39492ac0..7a889c3534da 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -24,14 +24,19 @@
#include "jni.h"
using ::android::hardware::Return;
+using ::android::hardware::hidl_vec;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using ::android::hardware::tv::tuner::V1_0::FrontendEventType;
using ::android::hardware::tv::tuner::V1_0::FrontendId;
+using ::android::hardware::tv::tuner::V1_0::FrontendScanMessage;
+using ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
using ::android::hardware::tv::tuner::V1_0::IDemux;
using ::android::hardware::tv::tuner::V1_0::IFilter;
using ::android::hardware::tv::tuner::V1_0::IFilterCallback;
using ::android::hardware::tv::tuner::V1_0::IFrontend;
+using ::android::hardware::tv::tuner::V1_0::IFrontendCallback;
using ::android::hardware::tv::tuner::V1_0::ITuner;
namespace android {
@@ -41,6 +46,18 @@ struct FilterCallback : public IFilterCallback {
virtual Return<void> onFilterStatus(const DemuxFilterStatus status);
};
+struct FrontendCallback : public IFrontendCallback {
+ FrontendCallback(jweak tunerObj, FrontendId id);
+
+ virtual Return<void> onEvent(FrontendEventType frontendEventType);
+ virtual Return<void> onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage);
+ virtual Return<void> onScanMessage(
+ FrontendScanMessageType type, const FrontendScanMessage& message);
+
+ jweak mObject;
+ FrontendId mId;
+};
+
struct JTuner : public RefBase {
JTuner(JNIEnv *env, jobject thiz);
sp<ITuner> getTunerService();
@@ -55,6 +72,7 @@ private:
jclass mClass;
jweak mObject;
static sp<ITuner> mTuner;
+ hidl_vec<FrontendId> mFeIds;
sp<IFrontend> mFe;
sp<IDemux> mDemux;
int mDemuxId;
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
index 706727bf050e..d3d9b286ded6 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
@@ -16,100 +16,30 @@
package com.android.systemui;
-import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
-
-import android.content.Context;
-import android.os.PowerManager;
-import android.util.DisplayMetrics;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.assist.AssistManager;
import com.android.systemui.biometrics.AuthController;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.bubbles.BubbleController;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.doze.DozeLog;
import com.android.systemui.globalactions.GlobalActionsComponent;
import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.navigationbar.car.CarNavigationBar;
-import com.android.systemui.navigationbar.car.CarNavigationBarController;
import com.android.systemui.pip.PipUI;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.power.PowerUI;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsModule;
-import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.FeatureFlags;
-import com.android.systemui.statusbar.NavigationBarController;
-import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.NotificationViewHierarchyManager;
-import com.android.systemui.statusbar.PulseExpansionHandler;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.car.CarStatusBar;
-import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
-import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.car.CarStatusBarModule;
import com.android.systemui.statusbar.notification.InstantAppNotifier;
-import com.android.systemui.statusbar.notification.NewNotifPipeline;
-import com.android.systemui.statusbar.notification.NotificationAlertingManager;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
-import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.logging.NotifLog;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
-import com.android.systemui.statusbar.phone.AutoHideController;
-import com.android.systemui.statusbar.phone.BiometricUnlockController;
-import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.DozeScrimController;
-import com.android.systemui.statusbar.phone.DozeServiceHost;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.LightBarController;
-import com.android.systemui.statusbar.phone.LockscreenWallpaper;
-import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.phone.StatusBarWindowController;
-import com.android.systemui.statusbar.phone.StatusBarWindowViewController;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
-import com.android.systemui.statusbar.policy.RemoteInputUriController;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.tv.TvStatusBar;
import com.android.systemui.theme.ThemeOverlayController;
-import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.util.leak.GarbageMonitor;
import com.android.systemui.volume.VolumeUI;
-import javax.inject.Named;
-import javax.inject.Singleton;
-
import dagger.Binds;
-import dagger.Lazy;
import dagger.Module;
-import dagger.Provides;
import dagger.multibindings.ClassKey;
import dagger.multibindings.IntoMap;
/** Binder for car specific {@link SystemUI} modules. */
-@Module(includes = {RecentsModule.class})
+@Module(includes = {RecentsModule.class, CarStatusBarModule.class})
public abstract class CarSystemUIBinder {
/** Inject into AuthController. */
@Binds
@@ -219,147 +149,4 @@ public abstract class CarSystemUIBinder {
@IntoMap
@ClassKey(VolumeUI.class)
public abstract SystemUI bindVolumeUI(VolumeUI sysui);
-
- /**
- * Provides our instance of StatusBar which is considered optional.
- */
- @Provides
- @Singleton
- static CarStatusBar provideStatusBar(
- Context context,
- FeatureFlags featureFlags,
- LightBarController lightBarController,
- AutoHideController autoHideController,
- KeyguardUpdateMonitor keyguardUpdateMonitor,
- StatusBarIconController statusBarIconController,
- DozeLog dozeLog,
- InjectionInflationController injectionInflationController,
- PulseExpansionHandler pulseExpansionHandler,
- NotificationWakeUpCoordinator notificationWakeUpCoordinator,
- KeyguardBypassController keyguardBypassController,
- KeyguardStateController keyguardStateController,
- HeadsUpManagerPhone headsUpManagerPhone,
- DynamicPrivacyController dynamicPrivacyController,
- BypassHeadsUpNotifier bypassHeadsUpNotifier,
- @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
- Lazy<NewNotifPipeline> newNotifPipeline,
- FalsingManager falsingManager,
- BroadcastDispatcher broadcastDispatcher,
- RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
- NotificationGutsManager notificationGutsManager,
- NotificationLogger notificationLogger,
- NotificationEntryManager notificationEntryManager,
- NotificationInterruptionStateProvider notificationInterruptionStateProvider,
- NotificationViewHierarchyManager notificationViewHierarchyManager,
- ForegroundServiceController foregroundServiceController,
- AppOpsController appOpsController,
- KeyguardViewMediator keyguardViewMediator,
- ZenModeController zenModeController,
- NotificationAlertingManager notificationAlertingManager,
- DisplayMetrics displayMetrics,
- MetricsLogger metricsLogger,
- UiOffloadThread uiOffloadThread,
- NotificationMediaManager notificationMediaManager,
- NotificationLockscreenUserManager lockScreenUserManager,
- NotificationRemoteInputManager remoteInputManager,
- UserSwitcherController userSwitcherController,
- NetworkController networkController,
- BatteryController batteryController,
- SysuiColorExtractor colorExtractor,
- ScreenLifecycle screenLifecycle,
- WakefulnessLifecycle wakefulnessLifecycle,
- SysuiStatusBarStateController statusBarStateController,
- VibratorHelper vibratorHelper,
- BubbleController bubbleController,
- NotificationGroupManager groupManager,
- NotificationGroupAlertTransferHelper groupAlertTransferHelper,
- VisualStabilityManager visualStabilityManager,
- DeviceProvisionedController deviceProvisionedController,
- NavigationBarController navigationBarController,
- AssistManager assistManager,
- NotificationListener notificationListener,
- ConfigurationController configurationController,
- StatusBarWindowController statusBarWindowController,
- StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder,
- NotifLog notifLog,
- DozeParameters dozeParameters,
- ScrimController scrimController,
- Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
- Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
- DozeServiceHost dozeServiceHost,
- PowerManager powerManager,
- DozeScrimController dozeScrimController,
- CommandQueue commandQueue,
- PluginManager pluginManager,
- CarNavigationBarController carNavigationBarController,
- RemoteInputUriController remoteInputUriController) {
- return new CarStatusBar(
- context,
- featureFlags,
- lightBarController,
- autoHideController,
- keyguardUpdateMonitor,
- statusBarIconController,
- dozeLog,
- injectionInflationController,
- pulseExpansionHandler,
- notificationWakeUpCoordinator,
- keyguardBypassController,
- keyguardStateController,
- headsUpManagerPhone,
- dynamicPrivacyController,
- bypassHeadsUpNotifier,
- allowNotificationLongPress,
- newNotifPipeline,
- falsingManager,
- broadcastDispatcher,
- remoteInputQuickSettingsDisabler,
- notificationGutsManager,
- notificationLogger,
- notificationEntryManager,
- notificationInterruptionStateProvider,
- notificationViewHierarchyManager,
- foregroundServiceController,
- appOpsController,
- keyguardViewMediator,
- zenModeController,
- notificationAlertingManager,
- displayMetrics,
- metricsLogger,
- uiOffloadThread,
- notificationMediaManager,
- lockScreenUserManager,
- remoteInputManager,
- userSwitcherController,
- networkController,
- batteryController,
- colorExtractor,
- screenLifecycle,
- wakefulnessLifecycle,
- statusBarStateController,
- vibratorHelper,
- bubbleController,
- groupManager,
- groupAlertTransferHelper,
- visualStabilityManager,
- deviceProvisionedController,
- navigationBarController,
- assistManager,
- notificationListener,
- configurationController,
- statusBarWindowController,
- statusBarWindowViewControllerBuilder,
- notifLog,
- dozeParameters,
- scrimController,
- lockscreenWallpaperLazy,
- biometricUnlockControllerLazy,
- dozeServiceHost,
- powerManager,
- dozeScrimController,
- commandQueue,
- pluginManager,
- remoteInputUriController,
- carNavigationBarController);
- }
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index d3a6cde66e84..a6377b0395b7 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -28,6 +28,10 @@ import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerImpl;
import com.android.systemui.power.EnhancedEstimates;
import com.android.systemui.power.EnhancedEstimatesImpl;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsImplementation;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.car.CarStatusBar;
@@ -70,6 +74,12 @@ abstract class CarSystemUIModule {
@Singleton
@Provides
+ static Divider provideDivider(Context context) {
+ return new Divider(context);
+ }
+
+ @Singleton
+ @Provides
@Named(LEAK_REPORT_EMAIL_NAME)
static String provideLeakReportEmail() {
return "buganizer-system+181579@google.com";
@@ -95,6 +105,13 @@ abstract class CarSystemUIModule {
return SysUiServiceProvider.getComponent(context, StatusBar.class);
}
+ @Provides
+ @Singleton
+ static Recents provideRecents(Context context, RecentsImplementation recentsImplementation,
+ CommandQueue commandQueue) {
+ return new Recents(context, recentsImplementation, commandQueue);
+ }
+
@Binds
abstract SystemUIRootComponent bindSystemUIRootComponent(
CarSystemUIRootComponent systemUIRootComponent);
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 110b32b57878..c1515fc30b60 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -81,6 +81,7 @@ import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.car.CarQSFragment;
import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -92,6 +93,7 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
@@ -114,6 +116,7 @@ import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.LightsOutNotifController;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -131,11 +134,11 @@ import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.util.InjectionInflationController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Map;
+import java.util.Optional;
import javax.inject.Named;
@@ -244,7 +247,6 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
KeyguardUpdateMonitor keyguardUpdateMonitor,
StatusBarIconController statusBarIconController,
DozeLog dozeLog,
- InjectionInflationController injectionInflationController,
PulseExpansionHandler pulseExpansionHandler,
NotificationWakeUpCoordinator notificationWakeUpCoordinator,
KeyguardBypassController keyguardBypassController,
@@ -303,6 +305,9 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
CommandQueue commandQueue,
PluginManager pluginManager,
RemoteInputUriController remoteInputUriController,
+ Optional<Divider> dividerOptional,
+ SuperStatusBarViewFactory superStatusBarViewFactory,
+ LightsOutNotifController lightsOutNotifController,
/* Car Settings injected components. */
CarNavigationBarController carNavigationBarController) {
super(
@@ -313,7 +318,6 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
keyguardUpdateMonitor,
statusBarIconController,
dozeLog,
- injectionInflationController,
pulseExpansionHandler,
notificationWakeUpCoordinator,
keyguardBypassController,
@@ -372,7 +376,10 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
dozeScrimController,
commandQueue,
pluginManager,
- remoteInputUriController);
+ remoteInputUriController,
+ dividerOptional,
+ lightsOutNotifController,
+ superStatusBarViewFactory);
mScrimController = scrimController;
mCarNavigationBarController = carNavigationBarController;
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
new file mode 100644
index 000000000000..9b91843576ce
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
@@ -0,0 +1,252 @@
+/*
+ * 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;
+
+import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.util.DisplayMetrics;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.UiOffloadThread;
+import com.android.systemui.appops.AppOpsController;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.navigationbar.car.CarNavigationBarController;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.FeatureFlags;
+import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationViewHierarchyManager;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.StatusBarDependenciesModule;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.phone.AutoHideController;
+import com.android.systemui.statusbar.phone.BiometricUnlockController;
+import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.DozeScrimController;
+import com.android.systemui.statusbar.phone.DozeServiceHost;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.LightsOutNotifController;
+import com.android.systemui.statusbar.phone.LockscreenWallpaper;
+import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
+import com.android.systemui.statusbar.phone.StatusBarWindowViewController;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.ZenModeController;
+
+import java.util.Optional;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger Module providing {@link CarStatusBar}.
+ */
+@Module(includes = {StatusBarDependenciesModule.class})
+public class CarStatusBarModule {
+ /**
+ * Provides our instance of StatusBar which is considered optional.
+ */
+ @Provides
+ @Singleton
+ static CarStatusBar provideStatusBar(
+ Context context,
+ FeatureFlags featureFlags,
+ LightBarController lightBarController,
+ AutoHideController autoHideController,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ StatusBarIconController statusBarIconController,
+ DozeLog dozeLog,
+ PulseExpansionHandler pulseExpansionHandler,
+ NotificationWakeUpCoordinator notificationWakeUpCoordinator,
+ KeyguardBypassController keyguardBypassController,
+ KeyguardStateController keyguardStateController,
+ HeadsUpManagerPhone headsUpManagerPhone,
+ DynamicPrivacyController dynamicPrivacyController,
+ BypassHeadsUpNotifier bypassHeadsUpNotifier,
+ @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
+ Lazy<NewNotifPipeline> newNotifPipeline,
+ FalsingManager falsingManager,
+ BroadcastDispatcher broadcastDispatcher,
+ RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
+ NotificationGutsManager notificationGutsManager,
+ NotificationLogger notificationLogger,
+ NotificationEntryManager notificationEntryManager,
+ NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationViewHierarchyManager notificationViewHierarchyManager,
+ ForegroundServiceController foregroundServiceController,
+ AppOpsController appOpsController,
+ KeyguardViewMediator keyguardViewMediator,
+ ZenModeController zenModeController,
+ NotificationAlertingManager notificationAlertingManager,
+ DisplayMetrics displayMetrics,
+ MetricsLogger metricsLogger,
+ UiOffloadThread uiOffloadThread,
+ NotificationMediaManager notificationMediaManager,
+ NotificationLockscreenUserManager lockScreenUserManager,
+ NotificationRemoteInputManager remoteInputManager,
+ UserSwitcherController userSwitcherController,
+ NetworkController networkController,
+ BatteryController batteryController,
+ SysuiColorExtractor colorExtractor,
+ ScreenLifecycle screenLifecycle,
+ WakefulnessLifecycle wakefulnessLifecycle,
+ SysuiStatusBarStateController statusBarStateController,
+ VibratorHelper vibratorHelper,
+ BubbleController bubbleController,
+ NotificationGroupManager groupManager,
+ NotificationGroupAlertTransferHelper groupAlertTransferHelper,
+ VisualStabilityManager visualStabilityManager,
+ DeviceProvisionedController deviceProvisionedController,
+ NavigationBarController navigationBarController,
+ AssistManager assistManager,
+ NotificationListener notificationListener,
+ ConfigurationController configurationController,
+ StatusBarWindowController statusBarWindowController,
+ StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder,
+ NotifLog notifLog,
+ DozeParameters dozeParameters,
+ ScrimController scrimController,
+ Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
+ Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+ DozeServiceHost dozeServiceHost,
+ PowerManager powerManager,
+ DozeScrimController dozeScrimController,
+ CommandQueue commandQueue,
+ PluginManager pluginManager,
+ RemoteInputUriController remoteInputUriController,
+ Optional<Divider> dividerOptional,
+ SuperStatusBarViewFactory superStatusBarViewFactory,
+ LightsOutNotifController lightsOutNotifController,
+ CarNavigationBarController carNavigationBarController) {
+ return new CarStatusBar(
+ context,
+ featureFlags,
+ lightBarController,
+ autoHideController,
+ keyguardUpdateMonitor,
+ statusBarIconController,
+ dozeLog,
+ pulseExpansionHandler,
+ notificationWakeUpCoordinator,
+ keyguardBypassController,
+ keyguardStateController,
+ headsUpManagerPhone,
+ dynamicPrivacyController,
+ bypassHeadsUpNotifier,
+ allowNotificationLongPress,
+ newNotifPipeline,
+ falsingManager,
+ broadcastDispatcher,
+ remoteInputQuickSettingsDisabler,
+ notificationGutsManager,
+ notificationLogger,
+ notificationEntryManager,
+ notificationInterruptionStateProvider,
+ notificationViewHierarchyManager,
+ foregroundServiceController,
+ appOpsController,
+ keyguardViewMediator,
+ zenModeController,
+ notificationAlertingManager,
+ displayMetrics,
+ metricsLogger,
+ uiOffloadThread,
+ notificationMediaManager,
+ lockScreenUserManager,
+ remoteInputManager,
+ userSwitcherController,
+ networkController,
+ batteryController,
+ colorExtractor,
+ screenLifecycle,
+ wakefulnessLifecycle,
+ statusBarStateController,
+ vibratorHelper,
+ bubbleController,
+ groupManager,
+ groupAlertTransferHelper,
+ visualStabilityManager,
+ deviceProvisionedController,
+ navigationBarController,
+ assistManager,
+ notificationListener,
+ configurationController,
+ statusBarWindowController,
+ statusBarWindowViewControllerBuilder,
+ notifLog,
+ dozeParameters,
+ scrimController,
+ lockscreenWallpaperLazy,
+ biometricUnlockControllerLazy,
+ dozeServiceHost,
+ powerManager,
+ dozeScrimController,
+ commandQueue,
+ pluginManager,
+ remoteInputUriController,
+ dividerOptional,
+ superStatusBarViewFactory,
+ lightsOutNotifController,
+ carNavigationBarController);
+ }
+}
diff --git a/packages/ExternalStorageProvider/res/values-af/strings.xml b/packages/ExternalStorageProvider/res/values-af/strings.xml
index 96b25a42eed1..b7684a7ffd27 100644
--- a/packages/ExternalStorageProvider/res/values-af/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-af/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="app_label" msgid="7123375275748530234">"Eksterne berging"</string>
- <string name="storage_description" msgid="8541974407321172792">"Plaaslike berging"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Interne berging"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumente"</string>
+ <string name="app_label" msgid="748293919008814871">"Eksterne berging"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Plaaslike berging"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Interne berging"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumente"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-am/strings.xml b/packages/ExternalStorageProvider/res/values-am/strings.xml
index f2d308c045b1..49de54d582cc 100644
--- a/packages/ExternalStorageProvider/res/values-am/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-am/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="app_label" msgid="7123375275748530234">"ውጫዊ ማከማቻ"</string>
- <string name="storage_description" msgid="8541974407321172792">"አካባቢያዊ ማከማቻ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ውስጣዊ ማከማቻ"</string>
- <string name="root_documents" msgid="4051252304075469250">"ሰነዶች"</string>
+ <string name="app_label" msgid="748293919008814871">"ውጫዊ ማከማቻ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"አካባቢያዊ ማከማቻ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ውስጣዊ ማከማቻ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ሰነዶች"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ar/strings.xml b/packages/ExternalStorageProvider/res/values-ar/strings.xml
index a01fc02da6d9..878f56057b9e 100644
--- a/packages/ExternalStorageProvider/res/values-ar/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ar/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="app_label" msgid="7123375275748530234">"وحدة تخزين خارجية"</string>
- <string name="storage_description" msgid="8541974407321172792">"التخزين المحلي"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"وحدة تخزين داخلية"</string>
- <string name="root_documents" msgid="4051252304075469250">"مستندات"</string>
+ <string name="app_label" msgid="748293919008814871">"وحدة تخزين خارجية"</string>
+ <string name="storage_description" msgid="9176081505553938524">"التخزين المحلي"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"وحدة تخزين داخلية"</string>
+ <string name="root_documents" msgid="5695037589229175941">"مستندات"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-as/strings.xml b/packages/ExternalStorageProvider/res/values-as/strings.xml
index 278b84e15a30..92bb1aa5d04e 100644
--- a/packages/ExternalStorageProvider/res/values-as/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-as/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="app_label" msgid="7123375275748530234">"বাহ্যিক সঞ্চয়াগাৰ"</string>
- <string name="storage_description" msgid="8541974407321172792">"স্থানীয় সঞ্চয়াগাৰ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"আভ্যন্তৰীণ সঞ্চয়াগাৰ"</string>
- <string name="root_documents" msgid="4051252304075469250">"নথিপত্রসমূহ"</string>
+ <string name="app_label" msgid="748293919008814871">"বাহ্যিক সঞ্চয়াগাৰ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"স্থানীয় সঞ্চয়াগাৰ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"আভ্যন্তৰীণ সঞ্চয়াগাৰ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"নথিপত্রসমূহ"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-az/strings.xml b/packages/ExternalStorageProvider/res/values-az/strings.xml
index d8c17ee03107..605a11a6f083 100644
--- a/packages/ExternalStorageProvider/res/values-az/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-az/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="app_label" msgid="7123375275748530234">"Xarici Yaddaş"</string>
- <string name="storage_description" msgid="8541974407321172792">"Yerli yaddaş"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Daxili yaddaş"</string>
- <string name="root_documents" msgid="4051252304075469250">"Sənədlər"</string>
+ <string name="app_label" msgid="748293919008814871">"Xarici Yaddaş"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Yerli yaddaş"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Daxili yaddaş"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Sənədlər"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-b+sr+Latn/strings.xml b/packages/ExternalStorageProvider/res/values-b+sr+Latn/strings.xml
index 235b621097cb..88e34fee6be7 100644
--- a/packages/ExternalStorageProvider/res/values-b+sr+Latn/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-b+sr+Latn/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="app_label" msgid="7123375275748530234">"Spoljna memorija"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokalni memorijski prostor"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Interna memorija"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
+ <string name="app_label" msgid="748293919008814871">"Spoljna memorija"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokalni memorijski prostor"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Interna memorija"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-be/strings.xml b/packages/ExternalStorageProvider/res/values-be/strings.xml
index 911ff54cad6c..07c7da5a3dc0 100644
--- a/packages/ExternalStorageProvider/res/values-be/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-be/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="app_label" msgid="7123375275748530234">"Вонкавае сховішча"</string>
- <string name="storage_description" msgid="8541974407321172792">"Лакальнае сховішча"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Унутранае сховішча"</string>
- <string name="root_documents" msgid="4051252304075469250">"Дакументы"</string>
+ <string name="app_label" msgid="748293919008814871">"Вонкавае сховішча"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Лакальнае сховішча"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Унутранае сховішча"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Дакументы"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-bg/strings.xml b/packages/ExternalStorageProvider/res/values-bg/strings.xml
index e3b58e4fffb9..ca89dc5eb73f 100644
--- a/packages/ExternalStorageProvider/res/values-bg/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-bg/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="app_label" msgid="7123375275748530234">"Външно хранилище"</string>
- <string name="storage_description" msgid="8541974407321172792">"Локално хранилище"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Вътрешно хранилище"</string>
- <string name="root_documents" msgid="4051252304075469250">"Документи"</string>
+ <string name="app_label" msgid="748293919008814871">"Външно хранилище"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Локално хранилище"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Вътрешно хранилище"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Документи"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-bn/strings.xml b/packages/ExternalStorageProvider/res/values-bn/strings.xml
index 264d82a48bd1..2b7f6adedfe0 100644
--- a/packages/ExternalStorageProvider/res/values-bn/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-bn/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="app_label" msgid="7123375275748530234">"এক্সটারনাল স্টোরেজ"</string>
- <string name="storage_description" msgid="8541974407321172792">"স্থানীয় স্টোরেজ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ইন্টারনাল স্টোরেজ"</string>
- <string name="root_documents" msgid="4051252304075469250">"দস্তাবেজগুলি"</string>
+ <string name="app_label" msgid="748293919008814871">"এক্সটারনাল স্টোরেজ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"স্থানীয় স্টোরেজ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ইন্টারনাল স্টোরেজ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"দস্তাবেজগুলি"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-bs/strings.xml b/packages/ExternalStorageProvider/res/values-bs/strings.xml
index 1eb3020f4a7b..2c42df794fb9 100644
--- a/packages/ExternalStorageProvider/res/values-bs/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-bs/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="app_label" msgid="7123375275748530234">"Aplikacija za vanjsku pohranu"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokalna pohrana"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Interna pohrana"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
+ <string name="app_label" msgid="748293919008814871">"Aplikacija za vanjsku pohranu"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokalna pohrana"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Interna pohrana"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ca/strings.xml b/packages/ExternalStorageProvider/res/values-ca/strings.xml
index a67de7d39f7f..117a41659c8e 100644
--- a/packages/ExternalStorageProvider/res/values-ca/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ca/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="app_label" msgid="7123375275748530234">"Emmagatzematge extern"</string>
- <string name="storage_description" msgid="8541974407321172792">"Emmagatzematge local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Emmagatzematge intern"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
+ <string name="app_label" msgid="748293919008814871">"Emmagatzematge extern"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Emmagatzematge local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Emmagatzematge intern"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-cs/strings.xml b/packages/ExternalStorageProvider/res/values-cs/strings.xml
index b9c54b8c7686..761533dbf7c2 100644
--- a/packages/ExternalStorageProvider/res/values-cs/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-cs/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="app_label" msgid="7123375275748530234">"Externí úložiště"</string>
- <string name="storage_description" msgid="8541974407321172792">"Místní úložiště"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Interní úložiště"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenty"</string>
+ <string name="app_label" msgid="748293919008814871">"Externí úložiště"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Místní úložiště"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Interní úložiště"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenty"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-da/strings.xml b/packages/ExternalStorageProvider/res/values-da/strings.xml
index 4da141935bc3..9d89c8000eb1 100644
--- a/packages/ExternalStorageProvider/res/values-da/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-da/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="app_label" msgid="7123375275748530234">"Ekstern lagerplads"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokalt lager"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Intern lagerplads"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenter"</string>
+ <string name="app_label" msgid="748293919008814871">"Ekstern lagerplads"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokalt lager"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Intern lagerplads"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenter"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-de/strings.xml b/packages/ExternalStorageProvider/res/values-de/strings.xml
index 846152baad25..cb22276fddd3 100644
--- a/packages/ExternalStorageProvider/res/values-de/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-de/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="app_label" msgid="7123375275748530234">"Externer Speicher"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokaler Speicher"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Interner Speicher"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumente"</string>
+ <string name="app_label" msgid="748293919008814871">"Externer Speicher"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokaler Speicher"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Interner Speicher"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumente"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-el/strings.xml b/packages/ExternalStorageProvider/res/values-el/strings.xml
index 1e78e53de99f..02123db5bb0b 100644
--- a/packages/ExternalStorageProvider/res/values-el/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-el/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="app_label" msgid="7123375275748530234">"Εξωτερικός αποθηκευτικός χώρος"</string>
- <string name="storage_description" msgid="8541974407321172792">"Τοπικός χώρος αποθήκευσης"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Εσωτερικός αποθηκευτικός χώρος"</string>
- <string name="root_documents" msgid="4051252304075469250">"Έγγραφα"</string>
+ <string name="app_label" msgid="748293919008814871">"Εξωτερικός αποθηκευτικός χώρος"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Τοπικός χώρος αποθήκευσης"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Εσωτερικός αποθηκευτικός χώρος"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Έγγραφα"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-en-rAU/strings.xml b/packages/ExternalStorageProvider/res/values-en-rAU/strings.xml
index beaaf0d8556b..b6bdd4abc9be 100644
--- a/packages/ExternalStorageProvider/res/values-en-rAU/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-en-rAU/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="app_label" msgid="7123375275748530234">"External Storage"</string>
- <string name="storage_description" msgid="8541974407321172792">"Local storage"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Internal storage"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
+ <string name="app_label" msgid="748293919008814871">"External Storage"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Local storage"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Internal storage"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-en-rCA/strings.xml b/packages/ExternalStorageProvider/res/values-en-rCA/strings.xml
index beaaf0d8556b..b6bdd4abc9be 100644
--- a/packages/ExternalStorageProvider/res/values-en-rCA/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-en-rCA/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="app_label" msgid="7123375275748530234">"External Storage"</string>
- <string name="storage_description" msgid="8541974407321172792">"Local storage"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Internal storage"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
+ <string name="app_label" msgid="748293919008814871">"External Storage"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Local storage"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Internal storage"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-en-rGB/strings.xml b/packages/ExternalStorageProvider/res/values-en-rGB/strings.xml
index beaaf0d8556b..b6bdd4abc9be 100644
--- a/packages/ExternalStorageProvider/res/values-en-rGB/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-en-rGB/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="app_label" msgid="7123375275748530234">"External Storage"</string>
- <string name="storage_description" msgid="8541974407321172792">"Local storage"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Internal storage"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
+ <string name="app_label" msgid="748293919008814871">"External Storage"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Local storage"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Internal storage"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-en-rIN/strings.xml b/packages/ExternalStorageProvider/res/values-en-rIN/strings.xml
index beaaf0d8556b..b6bdd4abc9be 100644
--- a/packages/ExternalStorageProvider/res/values-en-rIN/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-en-rIN/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="app_label" msgid="7123375275748530234">"External Storage"</string>
- <string name="storage_description" msgid="8541974407321172792">"Local storage"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Internal storage"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
+ <string name="app_label" msgid="748293919008814871">"External Storage"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Local storage"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Internal storage"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-en-rXC/strings.xml b/packages/ExternalStorageProvider/res/values-en-rXC/strings.xml
index 5034d21a9fdf..afec1093412e 100644
--- a/packages/ExternalStorageProvider/res/values-en-rXC/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-en-rXC/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="app_label" msgid="7123375275748530234">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‏‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‎‎‏‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‏‎‏‎‎External Storage‎‏‎‎‏‎"</string>
- <string name="storage_description" msgid="8541974407321172792">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‎‎‏‏‎‎‎‎‎‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‏‎‏‏‎‏‏‎‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎Local storage‎‏‎‎‏‎"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‎‏‎‎‎‎‎‎‎‏‎‏‏‏‏‏‏‎Internal storage‎‏‎‎‏‎"</string>
- <string name="root_documents" msgid="4051252304075469250">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‎‎‎‏‏‏‏‎‎‎‎‏‎‎‎‎‎‎‏‏‎‎‎‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‎‎‎‏‏‏‎‎‎‎‏‎‎Documents‎‏‎‎‏‎"</string>
+ <string name="app_label" msgid="748293919008814871">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‏‎‎‎‏‎‎‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‏‏‎‎‏‏‏‎‎‎‎‏‏‎‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‏‏‏‎External Storage‎‏‎‎‏‎"</string>
+ <string name="storage_description" msgid="9176081505553938524">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‏‎‎‏‎‏‎‎‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‎‎‎‏‎‏‏‏‎‎‎Local storage‎‏‎‎‏‎"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‏‏‏‎‎‎‏‏‎‏‏‎‎‎‎‏‎‏‏‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎‏‏‎‎‎‏‏‏‎‏‏‎‎‏‏‎Internal storage‎‏‎‎‏‎"</string>
+ <string name="root_documents" msgid="5695037589229175941">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‎‎‏‏‏‎‎‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‎‎‎‏‎‎‏‎‎‎‎‏‎‏‎Documents‎‏‎‎‏‎"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-es-rUS/strings.xml b/packages/ExternalStorageProvider/res/values-es-rUS/strings.xml
index 826242227180..39392a544bd1 100644
--- a/packages/ExternalStorageProvider/res/values-es-rUS/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-es-rUS/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="app_label" msgid="7123375275748530234">"Almacenamiento externo"</string>
- <string name="storage_description" msgid="8541974407321172792">"Almacenamiento local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Almacenamiento interno"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
+ <string name="app_label" msgid="748293919008814871">"Almacenamiento externo"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Almacenamiento local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Almacenamiento interno"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documentos"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-es/strings.xml b/packages/ExternalStorageProvider/res/values-es/strings.xml
index 826242227180..39392a544bd1 100644
--- a/packages/ExternalStorageProvider/res/values-es/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-es/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="app_label" msgid="7123375275748530234">"Almacenamiento externo"</string>
- <string name="storage_description" msgid="8541974407321172792">"Almacenamiento local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Almacenamiento interno"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
+ <string name="app_label" msgid="748293919008814871">"Almacenamiento externo"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Almacenamiento local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Almacenamiento interno"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documentos"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-et/strings.xml b/packages/ExternalStorageProvider/res/values-et/strings.xml
index 095202fcfe9e..7bc135bc1b0b 100644
--- a/packages/ExternalStorageProvider/res/values-et/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-et/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="app_label" msgid="7123375275748530234">"Väline talletusruum"</string>
- <string name="storage_description" msgid="8541974407321172792">"Kohalik salvestusruum"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Sisemine salvestusruum"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumendid"</string>
+ <string name="app_label" msgid="748293919008814871">"Väline talletusruum"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Kohalik salvestusruum"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Sisemine salvestusruum"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumendid"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-eu/strings.xml b/packages/ExternalStorageProvider/res/values-eu/strings.xml
index c0e8cdd4f7e0..fb438941ec3f 100644
--- a/packages/ExternalStorageProvider/res/values-eu/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-eu/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="app_label" msgid="7123375275748530234">"Kanpoko memoria"</string>
- <string name="storage_description" msgid="8541974407321172792">"Biltegi lokala"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Barneko memoria"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumentuak"</string>
+ <string name="app_label" msgid="748293919008814871">"Kanpoko memoria"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Biltegi lokala"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Barneko memoria"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumentuak"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-fa/strings.xml b/packages/ExternalStorageProvider/res/values-fa/strings.xml
index 0de4d4d51cbf..9eabfd027da2 100644
--- a/packages/ExternalStorageProvider/res/values-fa/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-fa/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="app_label" msgid="7123375275748530234">"حافظه خارجی"</string>
- <string name="storage_description" msgid="8541974407321172792">"فضای ذخیره‌سازی محلی"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"حافظهٔ داخلی"</string>
- <string name="root_documents" msgid="4051252304075469250">"اسناد"</string>
+ <string name="app_label" msgid="748293919008814871">"حافظه خارجی"</string>
+ <string name="storage_description" msgid="9176081505553938524">"فضای ذخیره‌سازی محلی"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"حافظهٔ داخلی"</string>
+ <string name="root_documents" msgid="5695037589229175941">"اسناد"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-fi/strings.xml b/packages/ExternalStorageProvider/res/values-fi/strings.xml
index 661956805157..bbb1c4fefbfc 100644
--- a/packages/ExternalStorageProvider/res/values-fi/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-fi/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="app_label" msgid="7123375275748530234">"Ulkoinen tallennustila"</string>
- <string name="storage_description" msgid="8541974407321172792">"Paikallinen tallennustila"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Sisäinen tallennustila"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumentit"</string>
+ <string name="app_label" msgid="748293919008814871">"Ulkoinen tallennustila"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Paikallinen tallennustila"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Sisäinen tallennustila"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumentit"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-fr-rCA/strings.xml b/packages/ExternalStorageProvider/res/values-fr-rCA/strings.xml
index e1e8f17efcb7..6c07457388bb 100644
--- a/packages/ExternalStorageProvider/res/values-fr-rCA/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-fr-rCA/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="app_label" msgid="7123375275748530234">"Stockage externe"</string>
- <string name="storage_description" msgid="8541974407321172792">"Stockage local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Mémoire de stockage interne"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
+ <string name="app_label" msgid="748293919008814871">"Stockage externe"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Stockage local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Mémoire de stockage interne"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-fr/strings.xml b/packages/ExternalStorageProvider/res/values-fr/strings.xml
index e1e8f17efcb7..6c07457388bb 100644
--- a/packages/ExternalStorageProvider/res/values-fr/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-fr/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="app_label" msgid="7123375275748530234">"Stockage externe"</string>
- <string name="storage_description" msgid="8541974407321172792">"Stockage local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Mémoire de stockage interne"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
+ <string name="app_label" msgid="748293919008814871">"Stockage externe"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Stockage local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Mémoire de stockage interne"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-gl/strings.xml b/packages/ExternalStorageProvider/res/values-gl/strings.xml
index eeb2f51517f7..91d957164b4a 100644
--- a/packages/ExternalStorageProvider/res/values-gl/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-gl/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="app_label" msgid="7123375275748530234">"Almacenamento externo"</string>
- <string name="storage_description" msgid="8541974407321172792">"Almacenamento local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Almacenamento interno"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
+ <string name="app_label" msgid="748293919008814871">"Almacenamento externo"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Almacenamento local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Almacenamento interno"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documentos"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-gu/strings.xml b/packages/ExternalStorageProvider/res/values-gu/strings.xml
index 3f59dd3889fb..fc9a34d5b628 100644
--- a/packages/ExternalStorageProvider/res/values-gu/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-gu/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="app_label" msgid="7123375275748530234">"બાહ્ય સંગ્રહ"</string>
- <string name="storage_description" msgid="8541974407321172792">"સ્થાનિક સ્ટોરેજ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"આંતરિક સ્ટોરેજ"</string>
- <string name="root_documents" msgid="4051252304075469250">"દસ્તાવેજો"</string>
+ <string name="app_label" msgid="748293919008814871">"બાહ્ય સંગ્રહ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"સ્થાનિક સ્ટોરેજ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"આંતરિક સ્ટોરેજ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"દસ્તાવેજો"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-hi/strings.xml b/packages/ExternalStorageProvider/res/values-hi/strings.xml
index f4248711a7dd..76f27ff11a30 100644
--- a/packages/ExternalStorageProvider/res/values-hi/strings.xml
+++ b/packages/ExternalStorageProvider/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="app_label" msgid="7123375275748530234">"बाहरी मेमोरी"</string>
- <string name="storage_description" msgid="8541974407321172792">"स्थानीय जगह"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"मोबाइल मेमोरी"</string>
- <string name="root_documents" msgid="4051252304075469250">"दस्तावेज़"</string>
+ <string name="app_label" msgid="748293919008814871">"बाहरी मेमोरी"</string>
+ <string name="storage_description" msgid="9176081505553938524">"स्थानीय जगह"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"मोबाइल मेमोरी"</string>
+ <string name="root_documents" msgid="5695037589229175941">"दस्तावेज़"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-hr/strings.xml b/packages/ExternalStorageProvider/res/values-hr/strings.xml
index 1dd696e7c5ac..bf0ad0c4c8b1 100644
--- a/packages/ExternalStorageProvider/res/values-hr/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-hr/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="app_label" msgid="7123375275748530234">"Vanjska pohrana"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokalna pohrana"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Unutarnja pohrana"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
+ <string name="app_label" msgid="748293919008814871">"Vanjska pohrana"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokalna pohrana"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Unutarnja pohrana"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-hu/strings.xml b/packages/ExternalStorageProvider/res/values-hu/strings.xml
index 8201630b51a3..021a8bb7a983 100644
--- a/packages/ExternalStorageProvider/res/values-hu/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-hu/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="app_label" msgid="7123375275748530234">"Külső tárhely"</string>
- <string name="storage_description" msgid="8541974407321172792">"Helyi tárhely"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Belső tárhely"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumentumok"</string>
+ <string name="app_label" msgid="748293919008814871">"Külső tárhely"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Helyi tárhely"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Belső tárhely"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumentumok"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-hy/strings.xml b/packages/ExternalStorageProvider/res/values-hy/strings.xml
index b8c2ea7eaf5c..b846d2835282 100644
--- a/packages/ExternalStorageProvider/res/values-hy/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-hy/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="app_label" msgid="7123375275748530234">"Արտաքին պահոց"</string>
- <string name="storage_description" msgid="8541974407321172792">"Սարքի հիշողություն"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Ներքին պահոց"</string>
- <string name="root_documents" msgid="4051252304075469250">"Փաստաթղթեր"</string>
+ <string name="app_label" msgid="748293919008814871">"Արտաքին պահոց"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Սարքի հիշողություն"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Ներքին պահոց"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Փաստաթղթեր"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-in/strings.xml b/packages/ExternalStorageProvider/res/values-in/strings.xml
index f91d1a56ae6c..950e906af112 100644
--- a/packages/ExternalStorageProvider/res/values-in/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-in/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="app_label" msgid="7123375275748530234">"Penyimpanan Eksternal"</string>
- <string name="storage_description" msgid="8541974407321172792">"Penyimpanan lokal"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Penyimpanan internal"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumen"</string>
+ <string name="app_label" msgid="748293919008814871">"Penyimpanan Eksternal"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Penyimpanan lokal"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Penyimpanan internal"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumen"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-is/strings.xml b/packages/ExternalStorageProvider/res/values-is/strings.xml
index adaf0d46a03b..cac2edb34ffb 100644
--- a/packages/ExternalStorageProvider/res/values-is/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-is/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="app_label" msgid="7123375275748530234">"Ytri geymsla"</string>
- <string name="storage_description" msgid="8541974407321172792">"Staðbundin vistun"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Innbyggð geymsla"</string>
- <string name="root_documents" msgid="4051252304075469250">"Skjöl"</string>
+ <string name="app_label" msgid="748293919008814871">"Ytri geymsla"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Staðbundin vistun"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Innbyggð geymsla"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Skjöl"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-it/strings.xml b/packages/ExternalStorageProvider/res/values-it/strings.xml
index 35ba7f39afde..3a59beddceaa 100644
--- a/packages/ExternalStorageProvider/res/values-it/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-it/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="app_label" msgid="7123375275748530234">"Archivio esterno"</string>
- <string name="storage_description" msgid="8541974407321172792">"Archiviazione locale"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Memoria interna"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documenti"</string>
+ <string name="app_label" msgid="748293919008814871">"Archivio esterno"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Archiviazione locale"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Memoria interna"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-iw/strings.xml b/packages/ExternalStorageProvider/res/values-iw/strings.xml
index f98f43939c2c..3027a4089ffa 100644
--- a/packages/ExternalStorageProvider/res/values-iw/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-iw/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="app_label" msgid="7123375275748530234">"אחסון חיצוני"</string>
- <string name="storage_description" msgid="8541974407321172792">"אחסון מקומי"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"אחסון פנימי"</string>
- <string name="root_documents" msgid="4051252304075469250">"מסמכים"</string>
+ <string name="app_label" msgid="748293919008814871">"אחסון חיצוני"</string>
+ <string name="storage_description" msgid="9176081505553938524">"אחסון מקומי"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"אחסון פנימי"</string>
+ <string name="root_documents" msgid="5695037589229175941">"מסמכים"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ja/strings.xml b/packages/ExternalStorageProvider/res/values-ja/strings.xml
index c1623d4c808b..ad041233fc9b 100644
--- a/packages/ExternalStorageProvider/res/values-ja/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ja/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="app_label" msgid="7123375275748530234">"外部ストレージ"</string>
- <string name="storage_description" msgid="8541974407321172792">"ローカル ストレージ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"内部ストレージ"</string>
- <string name="root_documents" msgid="4051252304075469250">"ドキュメント"</string>
+ <string name="app_label" msgid="748293919008814871">"外部ストレージ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"ローカル ストレージ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"内部ストレージ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ドキュメント"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ka/strings.xml b/packages/ExternalStorageProvider/res/values-ka/strings.xml
index 3886efac7c36..e320acae8b9f 100644
--- a/packages/ExternalStorageProvider/res/values-ka/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ka/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="app_label" msgid="7123375275748530234">"გარე მეხსიერება"</string>
- <string name="storage_description" msgid="8541974407321172792">"ადგილობრივი მეხსიერება"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"შიდა მეხსიერება"</string>
- <string name="root_documents" msgid="4051252304075469250">"დოკუმენტები"</string>
+ <string name="app_label" msgid="748293919008814871">"გარე მეხსიერება"</string>
+ <string name="storage_description" msgid="9176081505553938524">"ადგილობრივი მეხსიერება"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"შიდა მეხსიერება"</string>
+ <string name="root_documents" msgid="5695037589229175941">"დოკუმენტები"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-kk/strings.xml b/packages/ExternalStorageProvider/res/values-kk/strings.xml
index f6ad94daca84..825b2d1bff97 100644
--- a/packages/ExternalStorageProvider/res/values-kk/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-kk/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="app_label" msgid="7123375275748530234">"Сыртқы жад"</string>
- <string name="storage_description" msgid="8541974407321172792">"Жергілікті жад"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Ішкі жад"</string>
- <string name="root_documents" msgid="4051252304075469250">"Құжаттар"</string>
+ <string name="app_label" msgid="748293919008814871">"Сыртқы жад"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Жергілікті жад"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Ішкі жад"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Құжаттар"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-km/strings.xml b/packages/ExternalStorageProvider/res/values-km/strings.xml
index a2bb92866643..cd87a0554e64 100644
--- a/packages/ExternalStorageProvider/res/values-km/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-km/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="app_label" msgid="7123375275748530234">"ឧបករណ៍​​ផ្ទុក​ខាងក្រៅ"</string>
- <string name="storage_description" msgid="8541974407321172792">"ទំហំផ្ទុកមូលដ្ឋាន"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ឧបករណ៍​ផ្ទុក​ខាង​ក្នុង"</string>
- <string name="root_documents" msgid="4051252304075469250">"ឯកសារ"</string>
+ <string name="app_label" msgid="748293919008814871">"ឧបករណ៍​​ផ្ទុក​ខាងក្រៅ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"ទំហំផ្ទុកមូលដ្ឋាន"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ឧបករណ៍​ផ្ទុក​ខាង​ក្នុង"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ឯកសារ"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-kn/strings.xml b/packages/ExternalStorageProvider/res/values-kn/strings.xml
index 2883e067275d..fe35079748c6 100644
--- a/packages/ExternalStorageProvider/res/values-kn/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-kn/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="app_label" msgid="7123375275748530234">"ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆ"</string>
- <string name="storage_description" msgid="8541974407321172792">"ಸ್ಥಳೀಯ ಸಂಗ್ರಹಣೆ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ಆಂತರಿಕ ಸಂಗ್ರಹಣೆ"</string>
- <string name="root_documents" msgid="4051252304075469250">"ಡಾಕ್ಯುಮೆಂಟ್‌ಗಳು"</string>
+ <string name="app_label" msgid="748293919008814871">"ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"ಸ್ಥಳೀಯ ಸಂಗ್ರಹಣೆ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ಆಂತರಿಕ ಸಂಗ್ರಹಣೆ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ಡಾಕ್ಯುಮೆಂಟ್‌ಗಳು"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ko/strings.xml b/packages/ExternalStorageProvider/res/values-ko/strings.xml
index 1fa3189e890c..6a255eb34db3 100644
--- a/packages/ExternalStorageProvider/res/values-ko/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ko/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="app_label" msgid="7123375275748530234">"외부 저장소"</string>
- <string name="storage_description" msgid="8541974407321172792">"로컬 저장소"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"내부 저장소"</string>
- <string name="root_documents" msgid="4051252304075469250">"문서"</string>
+ <string name="app_label" msgid="748293919008814871">"외부 저장소"</string>
+ <string name="storage_description" msgid="9176081505553938524">"로컬 저장소"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"내부 저장소"</string>
+ <string name="root_documents" msgid="5695037589229175941">"문서"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ky/strings.xml b/packages/ExternalStorageProvider/res/values-ky/strings.xml
index e7e34cb0efec..d11daec105d2 100644
--- a/packages/ExternalStorageProvider/res/values-ky/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ky/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="app_label" msgid="7123375275748530234">"Тышкы сактагыч"</string>
- <string name="storage_description" msgid="8541974407321172792">"Жергиликтүү сактагыч"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Ички сактагыч"</string>
- <string name="root_documents" msgid="4051252304075469250">"Документтер"</string>
+ <string name="app_label" msgid="748293919008814871">"Тышкы сактагыч"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Жергиликтүү сактагыч"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Ички сактагыч"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Документтер"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-lo/strings.xml b/packages/ExternalStorageProvider/res/values-lo/strings.xml
index ba344e3981ed..26f7a6ef2bdd 100644
--- a/packages/ExternalStorageProvider/res/values-lo/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-lo/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="app_label" msgid="7123375275748530234">"ບ່ອນຈັດເກັບຂໍ້ມູນພາຍນອກ"</string>
- <string name="storage_description" msgid="8541974407321172792">"ບ່ອນຈັດເກັບຂໍ້ມູນໃນເຄື່ອງ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ບ່ອນຈັດເກັບຂໍ້ມູນພາຍໃນ"</string>
- <string name="root_documents" msgid="4051252304075469250">"ເອ​ກະ​ສານ"</string>
+ <string name="app_label" msgid="748293919008814871">"ບ່ອນຈັດເກັບຂໍ້ມູນພາຍນອກ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"ບ່ອນຈັດເກັບຂໍ້ມູນໃນເຄື່ອງ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ບ່ອນຈັດເກັບຂໍ້ມູນພາຍໃນ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ເອ​ກະ​ສານ"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-lt/strings.xml b/packages/ExternalStorageProvider/res/values-lt/strings.xml
index a34567333744..beca24e5aa12 100644
--- a/packages/ExternalStorageProvider/res/values-lt/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-lt/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="app_label" msgid="7123375275748530234">"Išorinė atmintinė"</string>
- <string name="storage_description" msgid="8541974407321172792">"Vietinė saugykla"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Vidinė atmintinė"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumentai"</string>
+ <string name="app_label" msgid="748293919008814871">"Išorinė atmintinė"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Vietinė saugykla"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Vidinė atmintinė"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumentai"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-lv/strings.xml b/packages/ExternalStorageProvider/res/values-lv/strings.xml
index a3a3ed879325..9e362c4f00f0 100644
--- a/packages/ExternalStorageProvider/res/values-lv/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-lv/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="app_label" msgid="7123375275748530234">"Ārējā krātuve"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokālā krātuve"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Iekšējā atmiņa"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
+ <string name="app_label" msgid="748293919008814871">"Ārējā krātuve"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokālā krātuve"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Iekšējā atmiņa"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-mk/strings.xml b/packages/ExternalStorageProvider/res/values-mk/strings.xml
index 5ebf8a60658f..76c6d910f07f 100644
--- a/packages/ExternalStorageProvider/res/values-mk/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-mk/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="app_label" msgid="7123375275748530234">"Надворешна меморија"</string>
- <string name="storage_description" msgid="8541974407321172792">"Локална меморија"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Внатрешен капацитет"</string>
- <string name="root_documents" msgid="4051252304075469250">"Документи"</string>
+ <string name="app_label" msgid="748293919008814871">"Надворешна меморија"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Локална меморија"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Внатрешен капацитет"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Документи"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ml/strings.xml b/packages/ExternalStorageProvider/res/values-ml/strings.xml
index 2f88c792110b..fab3f162399c 100644
--- a/packages/ExternalStorageProvider/res/values-ml/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ml/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="app_label" msgid="7123375275748530234">"ബാഹ്യ സ്റ്റോറേജ്"</string>
- <string name="storage_description" msgid="8541974407321172792">"ലോക്കൽ സ്റ്റോറേജ്"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ആന്തരിക സ്റ്റോറേജ്"</string>
- <string name="root_documents" msgid="4051252304075469250">"പ്രമാണങ്ങൾ"</string>
+ <string name="app_label" msgid="748293919008814871">"ബാഹ്യ സ്റ്റോറേജ്"</string>
+ <string name="storage_description" msgid="9176081505553938524">"ലോക്കൽ സ്റ്റോറേജ്"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ആന്തരിക സ്റ്റോറേജ്"</string>
+ <string name="root_documents" msgid="5695037589229175941">"പ്രമാണങ്ങൾ"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-mn/strings.xml b/packages/ExternalStorageProvider/res/values-mn/strings.xml
index afd5d649dbd0..e227b7ea5e69 100644
--- a/packages/ExternalStorageProvider/res/values-mn/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-mn/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="app_label" msgid="7123375275748530234">"Гадаад сан"</string>
- <string name="storage_description" msgid="8541974407321172792">"Дотоод сан"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Дотоод сан"</string>
- <string name="root_documents" msgid="4051252304075469250">"Документүүд"</string>
+ <string name="app_label" msgid="748293919008814871">"Гадаад сан"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Дотоод сан"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Дотоод сан"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Документүүд"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-mr/strings.xml b/packages/ExternalStorageProvider/res/values-mr/strings.xml
index 79274404230f..30596102f2c1 100644
--- a/packages/ExternalStorageProvider/res/values-mr/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-mr/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="app_label" msgid="7123375275748530234">"बाह्य संचयन"</string>
- <string name="storage_description" msgid="8541974407321172792">"स्थानिक स्टोरेज"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"अंतर्गत स्टोरेज"</string>
- <string name="root_documents" msgid="4051252304075469250">"दस्तऐवज"</string>
+ <string name="app_label" msgid="748293919008814871">"बाह्य संचयन"</string>
+ <string name="storage_description" msgid="9176081505553938524">"स्थानिक स्टोरेज"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"अंतर्गत स्टोरेज"</string>
+ <string name="root_documents" msgid="5695037589229175941">"दस्तऐवज"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ms/strings.xml b/packages/ExternalStorageProvider/res/values-ms/strings.xml
index 4196acdfa4b7..ebc3ce203c81 100644
--- a/packages/ExternalStorageProvider/res/values-ms/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ms/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="app_label" msgid="7123375275748530234">"Storan Luaran"</string>
- <string name="storage_description" msgid="8541974407321172792">"Storan setempat"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Storan dalaman"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumen"</string>
+ <string name="app_label" msgid="748293919008814871">"Storan Luaran"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Storan setempat"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Storan dalaman"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumen"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-my/strings.xml b/packages/ExternalStorageProvider/res/values-my/strings.xml
index 1c7a276fe980..607819426ea2 100644
--- a/packages/ExternalStorageProvider/res/values-my/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-my/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="app_label" msgid="7123375275748530234">"ပြင်ပသိုလှောင်ရာပစ္စည်း"</string>
- <string name="storage_description" msgid="8541974407321172792">"စက်တွင်း သိုလှောင်ခန်း"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"စက်တွင်း သိုလှောင်ထားမှု"</string>
- <string name="root_documents" msgid="4051252304075469250">"စာရွက်စာတန်းများ"</string>
+ <string name="app_label" msgid="748293919008814871">"ပြင်ပသိုလှောင်ရာပစ္စည်း"</string>
+ <string name="storage_description" msgid="9176081505553938524">"စက်တွင်း သိုလှောင်ခန်း"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"စက်တွင်း သိုလှောင်ထားမှု"</string>
+ <string name="root_documents" msgid="5695037589229175941">"စာရွက်စာတန်းများ"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-nb/strings.xml b/packages/ExternalStorageProvider/res/values-nb/strings.xml
index 979cb30ca915..1992f723525d 100644
--- a/packages/ExternalStorageProvider/res/values-nb/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-nb/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="app_label" msgid="7123375275748530234">"Ekstern lagring"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokal lagring"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Intern lagring"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenter"</string>
+ <string name="app_label" msgid="748293919008814871">"Ekstern lagring"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokal lagring"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Intern lagring"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenter"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ne/strings.xml b/packages/ExternalStorageProvider/res/values-ne/strings.xml
index bbe9c42b73e4..bc8871ca479a 100644
--- a/packages/ExternalStorageProvider/res/values-ne/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ne/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="app_label" msgid="7123375275748530234">"बाह्य भण्डारण"</string>
- <string name="storage_description" msgid="8541974407321172792">"स्थानीय भण्डारण"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"आन्तरिक भण्डारण"</string>
- <string name="root_documents" msgid="4051252304075469250">"कागजातहरू"</string>
+ <string name="app_label" msgid="748293919008814871">"बाह्य भण्डारण"</string>
+ <string name="storage_description" msgid="9176081505553938524">"स्थानीय भण्डारण"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"आन्तरिक भण्डारण"</string>
+ <string name="root_documents" msgid="5695037589229175941">"कागजातहरू"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-nl/strings.xml b/packages/ExternalStorageProvider/res/values-nl/strings.xml
index cea2e9c80569..455ea50081ed 100644
--- a/packages/ExternalStorageProvider/res/values-nl/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-nl/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="app_label" msgid="7123375275748530234">"Externe opslag"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokale opslag"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Interne opslag"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documenten"</string>
+ <string name="app_label" msgid="748293919008814871">"Externe opslag"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokale opslag"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Interne opslag"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documenten"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-or/strings.xml b/packages/ExternalStorageProvider/res/values-or/strings.xml
index 5387dc7d7663..ba9b811da92a 100644
--- a/packages/ExternalStorageProvider/res/values-or/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-or/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="app_label" msgid="7123375275748530234">"ଏକ୍ସଟର୍ନଲ୍‌ ଷ୍ଟୋରେଜ୍‌"</string>
- <string name="storage_description" msgid="8541974407321172792">"ଲୋକାଲ୍‍ ଷ୍ଟୋରେଜ୍‍"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ଇଣ୍ଟର୍ନଲ୍‌ ଷ୍ଟୋରେଜ୍‌"</string>
- <string name="root_documents" msgid="4051252304075469250">"ଡକ୍ୟୁମେଣ୍ଟ"</string>
+ <string name="app_label" msgid="748293919008814871">"ଏକ୍ସଟର୍ନଲ୍‌ ଷ୍ଟୋରେଜ୍‌"</string>
+ <string name="storage_description" msgid="9176081505553938524">"ଲୋକାଲ୍‍ ଷ୍ଟୋରେଜ୍‍"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ଇଣ୍ଟର୍ନଲ୍‌ ଷ୍ଟୋରେଜ୍‌"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ଡକ୍ୟୁମେଣ୍ଟ"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-pa/strings.xml b/packages/ExternalStorageProvider/res/values-pa/strings.xml
index 4e9d777d4036..becd075e448c 100644
--- a/packages/ExternalStorageProvider/res/values-pa/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-pa/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="app_label" msgid="7123375275748530234">"ਬਾਹਰੀ ਸਟੋਰੇਜ"</string>
- <string name="storage_description" msgid="8541974407321172792">"ਸਥਾਨਕ ਸਟੋਰੇਜ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ਅੰਦਰੂਨੀ ਸਟੋਰੇਜ"</string>
- <string name="root_documents" msgid="4051252304075469250">"ਦਸਤਾਵੇਜ਼"</string>
+ <string name="app_label" msgid="748293919008814871">"ਬਾਹਰੀ ਸਟੋਰੇਜ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"ਸਥਾਨਕ ਸਟੋਰੇਜ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ਅੰਦਰੂਨੀ ਸਟੋਰੇਜ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ਦਸਤਾਵੇਜ਼"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-pl/strings.xml b/packages/ExternalStorageProvider/res/values-pl/strings.xml
index f710bad89abc..885f25ca1cb9 100644
--- a/packages/ExternalStorageProvider/res/values-pl/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-pl/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="app_label" msgid="7123375275748530234">"Pamięć zewnętrzna"</string>
- <string name="storage_description" msgid="8541974407321172792">"Pamięć lokalna"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Pamięć wewnętrzna"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenty"</string>
+ <string name="app_label" msgid="748293919008814871">"Pamięć zewnętrzna"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Pamięć lokalna"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Pamięć wewnętrzna"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenty"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-pt-rBR/strings.xml b/packages/ExternalStorageProvider/res/values-pt-rBR/strings.xml
index 96046ad5f3df..aa745f1d78d5 100644
--- a/packages/ExternalStorageProvider/res/values-pt-rBR/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-pt-rBR/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="app_label" msgid="7123375275748530234">"Armazenamento externo"</string>
- <string name="storage_description" msgid="8541974407321172792">"Armazenamento local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Armazenamento interno"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
+ <string name="app_label" msgid="748293919008814871">"Armazenamento externo"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Armazenamento local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Armazenamento interno"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documentos"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-pt-rPT/strings.xml b/packages/ExternalStorageProvider/res/values-pt-rPT/strings.xml
index 35de8ef46508..9683b4cd5ea4 100644
--- a/packages/ExternalStorageProvider/res/values-pt-rPT/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-pt-rPT/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="app_label" msgid="7123375275748530234">"Armazenamento externo"</string>
- <string name="storage_description" msgid="8541974407321172792">"Armazenamento local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Armazenamento interno"</string>
- <string name="root_documents" msgid="4051252304075469250">"Docs"</string>
+ <string name="app_label" msgid="748293919008814871">"Armazenamento externo"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Armazenamento local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Armazenamento interno"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Docs"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-pt/strings.xml b/packages/ExternalStorageProvider/res/values-pt/strings.xml
index 96046ad5f3df..aa745f1d78d5 100644
--- a/packages/ExternalStorageProvider/res/values-pt/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-pt/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="app_label" msgid="7123375275748530234">"Armazenamento externo"</string>
- <string name="storage_description" msgid="8541974407321172792">"Armazenamento local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Armazenamento interno"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
+ <string name="app_label" msgid="748293919008814871">"Armazenamento externo"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Armazenamento local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Armazenamento interno"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documentos"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ro/strings.xml b/packages/ExternalStorageProvider/res/values-ro/strings.xml
index aaa9e4184e8c..d0606546c1fb 100644
--- a/packages/ExternalStorageProvider/res/values-ro/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ro/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="app_label" msgid="7123375275748530234">"Stocare externă"</string>
- <string name="storage_description" msgid="8541974407321172792">"Stocare locală"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Stocare internă"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documente"</string>
+ <string name="app_label" msgid="748293919008814871">"Stocare externă"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Stocare locală"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Stocare internă"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documente"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ru/strings.xml b/packages/ExternalStorageProvider/res/values-ru/strings.xml
index 222532f313c9..55a7550b9160 100644
--- a/packages/ExternalStorageProvider/res/values-ru/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ru/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="app_label" msgid="7123375275748530234">"Внешний накопитель"</string>
- <string name="storage_description" msgid="8541974407321172792">"Локальное хранилище"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Внутренний накопитель"</string>
- <string name="root_documents" msgid="4051252304075469250">"Документы"</string>
+ <string name="app_label" msgid="748293919008814871">"Внешний накопитель"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Локальное хранилище"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Внутренний накопитель"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Документы"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-si/strings.xml b/packages/ExternalStorageProvider/res/values-si/strings.xml
index 1adebec909b2..deaa65f8f283 100644
--- a/packages/ExternalStorageProvider/res/values-si/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-si/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="app_label" msgid="7123375275748530234">"බාහිර ආචයනය"</string>
- <string name="storage_description" msgid="8541974407321172792">"පෙදෙසි ආචයනය"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"අභ්‍යන්තර ආචයනය"</string>
- <string name="root_documents" msgid="4051252304075469250">"ලේඛන"</string>
+ <string name="app_label" msgid="748293919008814871">"බාහිර ආචයනය"</string>
+ <string name="storage_description" msgid="9176081505553938524">"පෙදෙසි ආචයනය"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"අභ්‍යන්තර ආචයනය"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ලේඛන"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sk/strings.xml b/packages/ExternalStorageProvider/res/values-sk/strings.xml
index f94a72638a63..b51210f43f19 100644
--- a/packages/ExternalStorageProvider/res/values-sk/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sk/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="app_label" msgid="7123375275748530234">"Externý ukladací priestor"</string>
- <string name="storage_description" msgid="8541974407321172792">"Miestne úložisko"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Interné úložisko"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenty"</string>
+ <string name="app_label" msgid="748293919008814871">"Externý ukladací priestor"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Miestne úložisko"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Interné úložisko"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenty"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sl/strings.xml b/packages/ExternalStorageProvider/res/values-sl/strings.xml
index 7992e974a3b4..262c2b704e4d 100644
--- a/packages/ExternalStorageProvider/res/values-sl/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sl/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="app_label" msgid="7123375275748530234">"Zunanja shramba"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokalna shramba"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Notranja shramba"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
+ <string name="app_label" msgid="748293919008814871">"Zunanja shramba"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokalna shramba"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Notranja shramba"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sq/strings.xml b/packages/ExternalStorageProvider/res/values-sq/strings.xml
index f73cff1b33ac..2a5c557da8ff 100644
--- a/packages/ExternalStorageProvider/res/values-sq/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sq/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="app_label" msgid="7123375275748530234">"Hapësirë e jashtme ruajtjeje"</string>
- <string name="storage_description" msgid="8541974407321172792">"Hapësira ruajtëse lokale"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Hapësira e brendshme ruajtëse"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumente"</string>
+ <string name="app_label" msgid="748293919008814871">"Hapësirë e jashtme ruajtjeje"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Hapësira ruajtëse lokale"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Hapësira e brendshme ruajtëse"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumente"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sr/strings.xml b/packages/ExternalStorageProvider/res/values-sr/strings.xml
index 6a7be4cf34b7..b44ce184a6ab 100644
--- a/packages/ExternalStorageProvider/res/values-sr/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sr/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="app_label" msgid="7123375275748530234">"Спољна меморија"</string>
- <string name="storage_description" msgid="8541974407321172792">"Локални меморијски простор"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Интерна меморија"</string>
- <string name="root_documents" msgid="4051252304075469250">"Документи"</string>
+ <string name="app_label" msgid="748293919008814871">"Спољна меморија"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Локални меморијски простор"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Интерна меморија"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Документи"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sv/strings.xml b/packages/ExternalStorageProvider/res/values-sv/strings.xml
index 103e83037112..11afb192eeea 100644
--- a/packages/ExternalStorageProvider/res/values-sv/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sv/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="app_label" msgid="7123375275748530234">"Extern lagring"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokal lagring"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Intern lagring"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokument"</string>
+ <string name="app_label" msgid="748293919008814871">"Extern lagring"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokal lagring"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Intern lagring"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokument"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sw/strings.xml b/packages/ExternalStorageProvider/res/values-sw/strings.xml
index fec928c25b53..94231ff2a64b 100644
--- a/packages/ExternalStorageProvider/res/values-sw/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sw/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="app_label" msgid="7123375275748530234">"Hifadhi ya Nje"</string>
- <string name="storage_description" msgid="8541974407321172792">"Hifadhi ya ndani"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Hifadhi ya ndani"</string>
- <string name="root_documents" msgid="4051252304075469250">"Hati"</string>
+ <string name="app_label" msgid="748293919008814871">"Hifadhi ya Nje"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Hifadhi ya ndani"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Hifadhi ya ndani"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Hati"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ta/strings.xml b/packages/ExternalStorageProvider/res/values-ta/strings.xml
index 5d569404e7b5..1f25d9e1d143 100644
--- a/packages/ExternalStorageProvider/res/values-ta/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ta/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="app_label" msgid="7123375275748530234">"வெளிப்புறச் சேமிப்பிடம்"</string>
- <string name="storage_description" msgid="8541974407321172792">"சாதனச் சேமிப்பகம்"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"அகச் சேமிப்பிடம்"</string>
- <string name="root_documents" msgid="4051252304075469250">"ஆவணங்கள்"</string>
+ <string name="app_label" msgid="748293919008814871">"வெளிப்புறச் சேமிப்பிடம்"</string>
+ <string name="storage_description" msgid="9176081505553938524">"சாதனச் சேமிப்பகம்"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"அகச் சேமிப்பிடம்"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ஆவணங்கள்"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-te/strings.xml b/packages/ExternalStorageProvider/res/values-te/strings.xml
index 97ca29da4cab..773ae0ead926 100644
--- a/packages/ExternalStorageProvider/res/values-te/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-te/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="app_label" msgid="7123375275748530234">"బాహ్య నిల్వ"</string>
- <string name="storage_description" msgid="8541974407321172792">"స్థానిక నిల్వ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"అంతర్గత నిల్వ"</string>
- <string name="root_documents" msgid="4051252304075469250">"పత్రాలు"</string>
+ <string name="app_label" msgid="748293919008814871">"బాహ్య నిల్వ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"స్థానిక నిల్వ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"అంతర్గత నిల్వ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"పత్రాలు"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-th/strings.xml b/packages/ExternalStorageProvider/res/values-th/strings.xml
index 3a3304f1dd47..570a91a80d37 100644
--- a/packages/ExternalStorageProvider/res/values-th/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-th/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="app_label" msgid="7123375275748530234">"ที่จัดเก็บข้อมูลภายนอก"</string>
- <string name="storage_description" msgid="8541974407321172792">"พื้นที่เก็บข้อมูลในเครื่อง"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ที่จัดเก็บข้อมูลภายใน"</string>
- <string name="root_documents" msgid="4051252304075469250">"เอกสาร"</string>
+ <string name="app_label" msgid="748293919008814871">"ที่จัดเก็บข้อมูลภายนอก"</string>
+ <string name="storage_description" msgid="9176081505553938524">"พื้นที่เก็บข้อมูลในเครื่อง"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ที่จัดเก็บข้อมูลภายใน"</string>
+ <string name="root_documents" msgid="5695037589229175941">"เอกสาร"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-tl/strings.xml b/packages/ExternalStorageProvider/res/values-tl/strings.xml
index 7b66436d6764..0a35373f8081 100644
--- a/packages/ExternalStorageProvider/res/values-tl/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-tl/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="app_label" msgid="7123375275748530234">"External Storage"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokal na storage"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Internal storage"</string>
- <string name="root_documents" msgid="4051252304075469250">"Mga Dokumento"</string>
+ <string name="app_label" msgid="748293919008814871">"External Storage"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokal na storage"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Internal storage"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Mga Dokumento"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-tr/strings.xml b/packages/ExternalStorageProvider/res/values-tr/strings.xml
index 39cd4da77df8..2e358050f3be 100644
--- a/packages/ExternalStorageProvider/res/values-tr/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-tr/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="app_label" msgid="7123375275748530234">"Harici Depolama"</string>
- <string name="storage_description" msgid="8541974407321172792">"Yerel depolama"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Dahili depolama"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokümanlar"</string>
+ <string name="app_label" msgid="748293919008814871">"Harici Depolama"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Yerel depolama"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Dahili depolama"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokümanlar"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-uk/strings.xml b/packages/ExternalStorageProvider/res/values-uk/strings.xml
index 25acf03eee95..f01ad8190d70 100644
--- a/packages/ExternalStorageProvider/res/values-uk/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-uk/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="app_label" msgid="7123375275748530234">"Зовнішня пам’ять"</string>
- <string name="storage_description" msgid="8541974407321172792">"Локальна пам’ять"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Внутрішня пам’ять"</string>
- <string name="root_documents" msgid="4051252304075469250">"Документи"</string>
+ <string name="app_label" msgid="748293919008814871">"Зовнішня пам’ять"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Локальна пам’ять"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Внутрішня пам’ять"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Документи"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ur/strings.xml b/packages/ExternalStorageProvider/res/values-ur/strings.xml
index c22afd9f2d26..1aafdd929597 100644
--- a/packages/ExternalStorageProvider/res/values-ur/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ur/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="app_label" msgid="7123375275748530234">"بیرونی اسٹوریج"</string>
- <string name="storage_description" msgid="8541974407321172792">"مقامی اسٹوریج"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"داخلی اسٹوریج"</string>
- <string name="root_documents" msgid="4051252304075469250">"دستاویزات"</string>
+ <string name="app_label" msgid="748293919008814871">"بیرونی اسٹوریج"</string>
+ <string name="storage_description" msgid="9176081505553938524">"مقامی اسٹوریج"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"داخلی اسٹوریج"</string>
+ <string name="root_documents" msgid="5695037589229175941">"دستاویزات"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-uz/strings.xml b/packages/ExternalStorageProvider/res/values-uz/strings.xml
index 48f8fedf37f7..87ab668a9a1f 100644
--- a/packages/ExternalStorageProvider/res/values-uz/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-uz/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="app_label" msgid="7123375275748530234">"Tashqi xotira"</string>
- <string name="storage_description" msgid="8541974407321172792">"Mahalliy xotira"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Ichki xotira"</string>
- <string name="root_documents" msgid="4051252304075469250">"Hujjatlar"</string>
+ <string name="app_label" msgid="748293919008814871">"Tashqi xotira"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Mahalliy xotira"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Ichki xotira"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Hujjatlar"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-vi/strings.xml b/packages/ExternalStorageProvider/res/values-vi/strings.xml
index f7479c00e9d1..e898d2cc7c7c 100644
--- a/packages/ExternalStorageProvider/res/values-vi/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-vi/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="app_label" msgid="7123375275748530234">"Bộ nhớ ngoài"</string>
- <string name="storage_description" msgid="8541974407321172792">"Bộ nhớ cục bộ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Bộ nhớ trong"</string>
- <string name="root_documents" msgid="4051252304075469250">"Tài liệu"</string>
+ <string name="app_label" msgid="748293919008814871">"Bộ nhớ ngoài"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Bộ nhớ cục bộ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Bộ nhớ trong"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Tài liệu"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-zh-rCN/strings.xml b/packages/ExternalStorageProvider/res/values-zh-rCN/strings.xml
index aa6789fb27ba..5be613279740 100644
--- a/packages/ExternalStorageProvider/res/values-zh-rCN/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-zh-rCN/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="app_label" msgid="7123375275748530234">"外部存储设备"</string>
- <string name="storage_description" msgid="8541974407321172792">"本地存储空间"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"内部存储空间"</string>
- <string name="root_documents" msgid="4051252304075469250">"文档"</string>
+ <string name="app_label" msgid="748293919008814871">"外部存储设备"</string>
+ <string name="storage_description" msgid="9176081505553938524">"本地存储空间"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"内部存储空间"</string>
+ <string name="root_documents" msgid="5695037589229175941">"文档"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-zh-rHK/strings.xml b/packages/ExternalStorageProvider/res/values-zh-rHK/strings.xml
index 3458c64ca1b8..16717967eadc 100644
--- a/packages/ExternalStorageProvider/res/values-zh-rHK/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-zh-rHK/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="app_label" msgid="7123375275748530234">"外部儲存空間"</string>
- <string name="storage_description" msgid="8541974407321172792">"本機儲存空間"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"內部儲存空間"</string>
- <string name="root_documents" msgid="4051252304075469250">"文件"</string>
+ <string name="app_label" msgid="748293919008814871">"外部儲存空間"</string>
+ <string name="storage_description" msgid="9176081505553938524">"本機儲存空間"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"內部儲存空間"</string>
+ <string name="root_documents" msgid="5695037589229175941">"文件"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-zh-rTW/strings.xml b/packages/ExternalStorageProvider/res/values-zh-rTW/strings.xml
index 3458c64ca1b8..16717967eadc 100644
--- a/packages/ExternalStorageProvider/res/values-zh-rTW/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-zh-rTW/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="app_label" msgid="7123375275748530234">"外部儲存空間"</string>
- <string name="storage_description" msgid="8541974407321172792">"本機儲存空間"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"內部儲存空間"</string>
- <string name="root_documents" msgid="4051252304075469250">"文件"</string>
+ <string name="app_label" msgid="748293919008814871">"外部儲存空間"</string>
+ <string name="storage_description" msgid="9176081505553938524">"本機儲存空間"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"內部儲存空間"</string>
+ <string name="root_documents" msgid="5695037589229175941">"文件"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-zu/strings.xml b/packages/ExternalStorageProvider/res/values-zu/strings.xml
index 96f454bd8630..3878591ea500 100644
--- a/packages/ExternalStorageProvider/res/values-zu/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-zu/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="app_label" msgid="7123375275748530234">"Isitoreji sangaphandle"</string>
- <string name="storage_description" msgid="8541974407321172792">"Isitoreji sasendaweni"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Isitoreji sangaphakathi"</string>
- <string name="root_documents" msgid="4051252304075469250">"Amadokhumenti"</string>
+ <string name="app_label" msgid="748293919008814871">"Isitoreji sangaphandle"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Isitoreji sasendaweni"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Isitoreji sangaphakathi"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Amadokhumenti"</string>
</resources>
diff --git a/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java b/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
index 5dc9061a81a0..de45ea536e27 100644
--- a/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
+++ b/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
@@ -21,7 +21,6 @@ import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import java.io.IOException;
@@ -73,10 +72,12 @@ public class IndexableProcessor extends AbstractProcessor {
}
mRanOnce = true;
+ final ClassName searchIndexableData = ClassName.get(PACKAGE, "SearchIndexableData");
+
final FieldSpec providers = FieldSpec.builder(
ParameterizedTypeName.get(
ClassName.get(Set.class),
- TypeName.get(Class.class)),
+ searchIndexableData),
"mProviders",
Modifier.PRIVATE, Modifier.FINAL)
.initializer("new $T()", HashSet.class)
@@ -84,7 +85,7 @@ public class IndexableProcessor extends AbstractProcessor {
final MethodSpec addIndex = MethodSpec.methodBuilder("addIndex")
.addModifiers(Modifier.PUBLIC)
- .addParameter(ClassName.get(Class.class), "indexClass")
+ .addParameter(searchIndexableData, "indexClass")
.addCode("$N.add(indexClass);\n", providers)
.build();
@@ -113,19 +114,25 @@ public class IndexableProcessor extends AbstractProcessor {
SearchIndexable searchIndexable = element.getAnnotation(SearchIndexable.class);
int forTarget = searchIndexable.forTarget();
+ MethodSpec.Builder builder = baseConstructorBuilder;
+
if (forTarget == SearchIndexable.ALL) {
- baseConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = baseConstructorBuilder;
} else if ((forTarget & SearchIndexable.MOBILE) != 0) {
- mobileConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = mobileConstructorBuilder;
} else if ((forTarget & SearchIndexable.TV) != 0) {
- tvConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = tvConstructorBuilder;
} else if ((forTarget & SearchIndexable.WEAR) != 0) {
- wearConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = wearConstructorBuilder;
} else if ((forTarget & SearchIndexable.AUTO) != 0) {
- autoConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = autoConstructorBuilder;
} else if ((forTarget & SearchIndexable.ARC) != 0) {
- arcConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = arcConstructorBuilder;
}
+ builder.addCode(
+ "$N(new SearchIndexableData($L.class, $L"
+ + ".SEARCH_INDEX_DATA_PROVIDER));\n",
+ addIndex, className, className);
} else {
throw new IllegalStateException("Null classname from " + element);
}
@@ -137,7 +144,7 @@ public class IndexableProcessor extends AbstractProcessor {
.addModifiers(Modifier.PUBLIC)
.returns(ParameterizedTypeName.get(
ClassName.get(Collection.class),
- TypeName.get(Class.class)))
+ searchIndexableData))
.addCode("return $N;\n", providers)
.build();
diff --git a/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableData.java b/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableData.java
new file mode 100644
index 000000000000..8b8f2688b93f
--- /dev/null
+++ b/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableData.java
@@ -0,0 +1,48 @@
+/*
+ * 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.settingslib.search;
+
+/**
+ * A Bundle class used in {@link SearchIndexableResources} to provide search Index data.
+ */
+public class SearchIndexableData {
+ private final Class mTargetClass;
+ private final Indexable.SearchIndexProvider mSearchIndexProvider;
+
+ /**
+ * Constructs a SearchIndexableData
+ *
+ * @param targetClass The target opening class of the {@link Indexable.SearchIndexProvider}. It
+ * should be a {@link android.app.Activity} or fragment {@link
+ * androidx.fragment.app.Fragment}.
+ * But fragment is only supported in Android Settings. Other apps should use
+ * {@link android.app.Activity}
+ * @param provider provides searchable data for Android Settings
+ */
+ public SearchIndexableData(Class targetClass, Indexable.SearchIndexProvider provider) {
+ mTargetClass = targetClass;
+ mSearchIndexProvider = provider;
+ }
+
+ public Class getTargetClass() {
+ return mTargetClass;
+ }
+
+ public Indexable.SearchIndexProvider getSearchIndexProvider() {
+ return mSearchIndexProvider;
+ }
+}
diff --git a/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableResources.java b/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableResources.java
index 976647b3e88f..e00ca718ce1c 100644
--- a/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableResources.java
+++ b/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableResources.java
@@ -21,15 +21,12 @@ import java.util.Collection;
public interface SearchIndexableResources {
/**
- * Returns a collection of classes that should be indexed for search.
- *
- * Each class should have the SEARCH_INDEX_DATA_PROVIDER public static member.
+ * Returns a Collection of {@link SearchIndexableData} that should be indexed for search.
*/
- Collection<Class> getProviderValues();
+ Collection<SearchIndexableData> getProviderValues();
/**
- * For testing. Can't use @VisibleForTesting here because this builds as a host binary as well
- * as a device binary.
+ * Add {@link SearchIndexableData} for search in Android Settings.
*/
- void addIndex(Class indexClass);
+ void addIndex(SearchIndexableData indexBundle);
} \ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 0d972c5e2e0e..e660e43a60da 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -150,7 +150,7 @@ public class BluetoothUtils {
context.getContentResolver().takePersistableUriPermission(iconUri,
Intent.FLAG_GRANT_READ_URI_PERMISSION);
} catch (SecurityException e) {
- Log.e(TAG, "Failed to take persistable permission for: " + iconUri);
+ Log.e(TAG, "Failed to take persistable permission for: " + iconUri, e);
}
try {
final Bitmap bitmap = MediaStore.Images.Media.getBitmap(
@@ -165,6 +165,8 @@ public class BluetoothUtils {
}
} catch (IOException e) {
Log.e(TAG, "Failed to get drawable for: " + iconUri, e);
+ } catch (SecurityException e) {
+ Log.e(TAG, "Failed to get permission for: " + iconUri, e);
}
}
}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index b288eb7b5070..cd64a3880803 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -60,6 +60,9 @@
<uses-permission android:name="android.permission.GET_APP_OPS_STATS" />
<uses-permission android:name="android.permission.USE_RESERVED_DISK" />
+ <!-- to invoke ContentSuggestionsService -->
+ <uses-permission android:name="android.permission.MANAGE_CONTENT_SUGGESTIONS"/>
+
<!-- Networking and telephony -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 14371fe4b41b..64b2892efc9a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1120,8 +1120,6 @@
<dimen name="bubble_touch_padding">12dp</dimen>
<!-- Size of the circle around the bubbles when they're in the dismiss target. -->
<dimen name="bubble_dismiss_encircle_size">52dp</dimen>
- <!-- How much to inset the icon in the circle -->
- <dimen name="bubble_icon_inset">16dp</dimen>
<!-- Padding around the view displayed when the bubble is expanded -->
<dimen name="bubble_expanded_view_padding">4dp</dimen>
<!-- This should be at least the size of bubble_expanded_view_padding; it is used to include
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index 074ef53aa57c..acce41cc942e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -56,7 +56,9 @@ public class TaskStackChangeListeners extends TaskStackListener {
}
public void addListener(IActivityManager am, TaskStackChangeListener listener) {
- mTaskStackListeners.add(listener);
+ synchronized (mTaskStackListeners) {
+ mTaskStackListeners.add(listener);
+ }
if (!mRegistered) {
// Register mTaskStackListener to IActivityManager only once if needed.
try {
@@ -69,8 +71,12 @@ public class TaskStackChangeListeners extends TaskStackListener {
}
public void removeListener(TaskStackChangeListener listener) {
- mTaskStackListeners.remove(listener);
- if (mTaskStackListeners.isEmpty() && mRegistered) {
+ boolean isEmpty;
+ synchronized (mTaskStackListeners) {
+ mTaskStackListeners.remove(listener);
+ isEmpty = mTaskStackListeners.isEmpty();
+ }
+ if (isEmpty && mRegistered) {
// Unregister mTaskStackListener once we have no more listeners
try {
ActivityTaskManager.getService().unregisterTaskStackListener(this);
@@ -83,14 +89,17 @@ public class TaskStackChangeListeners extends TaskStackListener {
@Override
public void onTaskStackChanged() throws RemoteException {
- // Call the task changed callback for the non-ui thread listeners first
+ // Call the task changed callback for the non-ui thread listeners first. Copy to a set of
+ // temp listeners so that we don't lock on mTaskStackListeners while calling all the
+ // callbacks. This call is always on the same binder thread, so we can just synchronize
+ // on the copying of the listener list.
synchronized (mTaskStackListeners) {
- mTmpListeners.clear();
mTmpListeners.addAll(mTaskStackListeners);
}
for (int i = mTmpListeners.size() - 1; i >= 0; i--) {
mTmpListeners.get(i).onTaskStackChangedBackground();
}
+ mTmpListeners.clear();
mHandler.removeMessages(H.ON_TASK_STACK_CHANGED);
mHandler.sendEmptyMessage(H.ON_TASK_STACK_CHANGED);
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 46b4c6b7d44c..21b52c1e5b57 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -169,12 +169,15 @@ public class CarrierTextController {
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mSeparator = separator;
mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
- mSimSlotsNumber = ((TelephonyManager) context.getSystemService(
- Context.TELEPHONY_SERVICE)).getSupportedModemCount();
+ mSimSlotsNumber = getTelephonyManager().getSupportedModemCount();
mSimErrorState = new boolean[mSimSlotsNumber];
mMainHandler = Dependency.get(Dependency.MAIN_HANDLER);
}
+ private TelephonyManager getTelephonyManager() {
+ return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ }
+
/**
* Checks if there are faulty cards. Adds the text depending on the slot of the card
*
@@ -190,7 +193,7 @@ public class CarrierTextController {
CharSequence carrierTextForSimIOError = getCarrierTextForSimState(
IccCardConstants.State.CARD_IO_ERROR, carrier);
// mSimErrorState has the state of each sim indexed by slotID.
- for (int index = 0; index < mSimErrorState.length; index++) {
+ for (int index = 0; index < getTelephonyManager().getActiveModemCount(); index++) {
if (!mSimErrorState[index]) {
continue;
}
@@ -223,8 +226,7 @@ public class CarrierTextController {
* @param callback Callback to provide text updates
*/
public void setListening(CarrierTextCallback callback) {
- TelephonyManager telephonyManager = ((TelephonyManager) mContext
- .getSystemService(Context.TELEPHONY_SERVICE));
+ TelephonyManager telephonyManager = getTelephonyManager();
if (callback != null) {
mCarrierTextCallback = callback;
// TODO(b/140034799)
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 9c0a71c1f81d..b1502b9a0d63 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -104,7 +104,12 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
private void setLockedSimMessage() {
boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId);
- int count = TelephonyManager.getDefault().getSimCount();
+ int count = 1;
+ TelephonyManager telephonyManager =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ if (telephonyManager != null) {
+ count = telephonyManager.getActiveModemCount();
+ }
Resources rez = getResources();
String msg;
TypedArray array = mContext.obtainStyledAttributes(new int[] { R.attr.wallpaperTextColor });
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index fc888e11d3f5..70237a053e1e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -164,7 +164,12 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView {
}
boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId);
- int count = TelephonyManager.getDefault().getSimCount();
+ int count = 1;
+ TelephonyManager telephonyManager =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ if (telephonyManager != null) {
+ count = telephonyManager.getActiveModemCount();
+ }
Resources rez = getResources();
String msg;
TypedArray array = mContext.obtainStyledAttributes(new int[] { R.attr.wallpaperTextColor });
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 6685db130d4a..0b0922a7766f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -2649,8 +2649,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
// that don't return the complete set of values and have different types. In Keyguard we
// need IccCardConstants, but TelephonyManager would only give us
// TelephonyManager.SIM_STATE*, so we retrieve it manually.
- final TelephonyManager tele = TelephonyManager.from(mContext);
- int simState = tele.getSimState(slotId);
+ final TelephonyManager tele =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ int simState = (tele != null) ?
+ tele.getSimState(slotId) : TelephonyManager.SIM_STATE_UNKNOWN;
State state;
try {
state = State.intToState(simState);
diff --git a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
index a94952c5bc19..8e472f9c98a3 100644
--- a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
+++ b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
@@ -47,6 +47,7 @@ public class CornerHandleView extends View {
private int mLightColor;
private int mDarkColor;
private Path mPath;
+ private boolean mRequiresInvalidate;
public CornerHandleView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -67,6 +68,15 @@ public class CornerHandleView extends View {
updatePath();
}
+ @Override
+ public void setAlpha(float alpha) {
+ super.setAlpha(alpha);
+ if (alpha > 0f && mRequiresInvalidate) {
+ mRequiresInvalidate = false;
+ invalidate();
+ }
+ }
+
private void updatePath() {
mPath = new Path();
@@ -104,11 +114,16 @@ public class CornerHandleView extends View {
* appropriately. Intention is to match the home handle color.
*/
public void updateDarkness(float darkIntensity) {
- mPaint.setColor((int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
- mLightColor,
- mDarkColor));
- if (getVisibility() == VISIBLE) {
- invalidate();
+ int color = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
+ mLightColor, mDarkColor);
+ if (mPaint.getColor() != color) {
+ mPaint.setColor(color);
+ if (getVisibility() == VISIBLE && getAlpha() > 0) {
+ invalidate();
+ } else {
+ // If we are currently invisible, then invalidate when we are next made visible
+ mRequiresInvalidate = true;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 0a547b6bf051..b5245973f818 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -33,6 +33,7 @@ import com.android.systemui.dagger.SystemUIRootComponent;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
@@ -124,6 +125,15 @@ public class SystemUIFactory {
return new StatusBarKeyguardViewManager(context, viewMediatorCallback, lockPatternUtils);
}
+ /**
+ * Creates an instance of ScreenshotNotificationSmartActionsProvider.
+ * This method is overridden in vendor specific implementation of Sys UI.
+ */
+ public ScreenshotNotificationSmartActionsProvider
+ createScreenshotNotificationSmartActionsProvider() {
+ return new ScreenshotNotificationSmartActionsProvider();
+ }
+
public KeyguardBouncer createKeyguardBouncer(Context context, ViewMediatorCallback callback,
LockPatternUtils lockPatternUtils, ViewGroup container,
DismissCallbackRegistry dismissCallbackRegistry,
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
index 9a277e8fa77c..46ae84a95fad 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
@@ -249,7 +249,7 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
public void onModeDeactivated() {
mAssistHandleCallbacks = null;
if (mContext != null) {
- mContext.unregisterReceiver(mDefaultHomeBroadcastReceiver);
+ mBroadcastDispatcher.get().unregisterReceiver(mDefaultHomeBroadcastReceiver);
Settings.Secure.putLong(mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, 0);
Settings.Secure.putInt(mContext.getContentResolver(), LEARNING_EVENT_COUNT_KEY, 0);
Settings.Secure.putLong(mContext.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java b/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java
index baa3a4a938c1..c641943278d4 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java
@@ -67,8 +67,10 @@ public final class EdgeLight {
}
/** Sets the edge light color. */
- public void setColor(@ColorInt int color) {
+ public boolean setColor(@ColorInt int color) {
+ boolean changed = mColor != color;
mColor = color;
+ return changed;
}
/** Returns the edge light length, in units of the total device perimeter. */
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
index 570b911cd400..e5121a8ea35c 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
@@ -259,10 +259,13 @@ public class InvocationLightsView extends View
if (mUseNavBarColor) {
@ColorInt int invocationColor = (int) ArgbEvaluator.getInstance().evaluate(
darkIntensity, mLightColor, mDarkColor);
+ boolean changed = true;
for (EdgeLight light : mAssistInvocationLights) {
- light.setColor(invocationColor);
+ changed &= light.setColor(invocationColor);
+ }
+ if (changed) {
+ invalidate();
}
- invalidate();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
index f5f1fad71b14..84a592d68627 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
@@ -298,7 +298,10 @@ public abstract class AuthBiometricView extends LinearLayout {
.getDimension(R.dimen.biometric_dialog_icon_padding);
mIconView.setY(getHeight() - mIconView.getHeight() - iconPadding);
- final int newHeight = mIconView.getHeight() + 2 * (int) iconPadding;
+ // Subtract the vertical padding from the new height since it's only used to create
+ // extra space between the other elements, and not part of the actual icon.
+ final int newHeight = mIconView.getHeight() + 2 * (int) iconPadding
+ - mIconView.getPaddingTop() - mIconView.getPaddingBottom();
mPanelController.updateForContentDimensions(mMediumWidth, newHeight,
0 /* animateDurationMs */);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 516de709c34f..6b0d3c807079 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -23,7 +23,10 @@ import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
import android.app.TaskStackListener;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.hardware.biometrics.Authenticator;
@@ -85,6 +88,28 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
}
}
+ @VisibleForTesting
+ final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mCurrentDialog != null
+ && Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
+ Log.w(TAG, "ACTION_CLOSE_SYSTEM_DIALOGS received");
+ mCurrentDialog.dismissWithoutCallback(true /* animate */);
+ mCurrentDialog = null;
+
+ try {
+ if (mReceiver != null) {
+ mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
+ mReceiver = null;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Remote exception", e);
+ }
+ }
+ }
+ };
+
private final Runnable mTaskStackChangedRunnable = () -> {
if (mCurrentDialog != null) {
try {
@@ -204,6 +229,11 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
super(context);
mCommandQueue = commandQueue;
mInjector = injector;
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+
+ context.registerReceiver(mBroadcastReceiver, filter);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
index 24357a740331..d50666c1b3cf 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
@@ -27,6 +27,8 @@ import android.os.UserHandle
import android.util.ArrayMap
import android.util.ArraySet
import android.util.Log
+import androidx.annotation.MainThread
+import com.android.internal.util.Preconditions
import com.android.systemui.Dumpable
import java.io.FileDescriptor
import java.io.PrintWriter
@@ -72,7 +74,14 @@ class UserBroadcastDispatcher(
internal fun isRegistered() = registered.get()
- private val registerReceiver = Runnable {
+ // Only modify in BG thread
+ private val actionsToReceivers = ArrayMap<String, MutableSet<ReceiverData>>()
+ private val receiverToReceiverData = ArrayMap<BroadcastReceiver, MutableSet<ReceiverData>>()
+
+ // Only call on BG thread as it reads from the maps
+ private fun createFilter(): IntentFilter {
+ Preconditions.checkState(bgHandler.looper.isCurrentThread,
+ "This method should only be called from BG thread")
val categories = mutableSetOf<String>()
receiverToReceiverData.values.flatten().forEach {
it.filter.categoriesIterator()?.asSequence()?.let {
@@ -80,30 +89,13 @@ class UserBroadcastDispatcher(
}
}
val intentFilter = IntentFilter().apply {
- actionsToReceivers.keys.forEach { addAction(it) }
+ // The keys of the arrayMap are of type String! so null check is needed
+ actionsToReceivers.keys.forEach { if (it != null) addAction(it) else Unit }
categories.forEach { addCategory(it) }
}
-
- if (registered.get()) {
- context.unregisterReceiver(this)
- registered.set(false)
- }
- // Short interval without receiver, this can be problematic
- if (intentFilter.countActions() > 0 && !registered.get()) {
- context.registerReceiverAsUser(
- this,
- UserHandle.of(userId),
- intentFilter,
- null,
- bgHandler)
- registered.set(true)
- }
+ return intentFilter
}
- // Only modify in BG thread
- private val actionsToReceivers = ArrayMap<String, MutableSet<ReceiverData>>()
- private val receiverToReceiverData = ArrayMap<BroadcastReceiver, MutableSet<ReceiverData>>()
-
override fun onReceive(context: Context, intent: Intent) {
val id = if (DEBUG) index.getAndIncrement() else 0
if (DEBUG) Log.w(TAG, "[$id] Received $intent")
@@ -126,6 +118,8 @@ class UserBroadcastDispatcher(
}
private fun handleRegisterReceiver(receiverData: ReceiverData) {
+ Preconditions.checkState(bgHandler.looper.isCurrentThread,
+ "This method should only be called from BG thread")
if (DEBUG) Log.w(TAG, "Register receiver: ${receiverData.receiver}")
receiverToReceiverData.getOrPut(receiverData.receiver, { ArraySet() }).add(receiverData)
var changed = false
@@ -138,11 +132,13 @@ class UserBroadcastDispatcher(
}.add(receiverData)
}
if (changed) {
- mainHandler.post(registerReceiver)
+ createFilterAndRegisterReceiverBG()
}
}
private fun handleUnregisterReceiver(receiver: BroadcastReceiver) {
+ Preconditions.checkState(bgHandler.looper.isCurrentThread,
+ "This method should only be called from BG thread")
if (DEBUG) Log.w(TAG, "Unregister receiver: $receiver")
val actions = receiverToReceiverData.getOrElse(receiver) { return }
.flatMap { it.filter.actionsIterator().asSequence().asIterable() }.toSet()
@@ -156,10 +152,16 @@ class UserBroadcastDispatcher(
}
}
if (changed) {
- mainHandler.post(registerReceiver)
+ createFilterAndRegisterReceiverBG()
}
}
+ // Only call this from a BG thread
+ private fun createFilterAndRegisterReceiverBG() {
+ val intentFilter = createFilter()
+ mainHandler.post(RegisterReceiverRunnable(intentFilter))
+ }
+
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
pw.println(" Registered=${registered.get()}")
actionsToReceivers.forEach { (action, list) ->
@@ -191,4 +193,30 @@ class UserBroadcastDispatcher(
}
}
}
+
+ private inner class RegisterReceiverRunnable(val intentFilter: IntentFilter) : Runnable {
+
+ /*
+ * Registers and unregisters the BroadcastReceiver
+ *
+ * Must be called from Main Thread
+ */
+ @MainThread
+ override fun run() {
+ if (registered.get()) {
+ context.unregisterReceiver(this@UserBroadcastDispatcher)
+ registered.set(false)
+ }
+ // Short interval without receiver, this can be problematic
+ if (intentFilter.countActions() > 0 && !registered.get()) {
+ context.registerReceiverAsUser(
+ this@UserBroadcastDispatcher,
+ UserHandle.of(userId),
+ intentFilter,
+ null,
+ bgHandler)
+ registered.set(true)
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 7600b2f3ed7a..f8e45d4c8b63 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -134,6 +134,10 @@ class Bubble {
return mAppName;
}
+ public Drawable getUserBadgedAppIcon() {
+ return mUserBadgedAppIcon;
+ }
+
boolean isInflated() {
return mInflated;
}
@@ -165,7 +169,6 @@ class Bubble {
mIconView = (BubbleView) inflater.inflate(
R.layout.bubble_view, stackView, false /* attachToRoot */);
mIconView.setBubble(this);
- mIconView.setAppIcon(mUserBadgedAppIcon);
mExpandedView = (BubbleExpandedView) inflater.inflate(
R.layout.bubble_expanded_view, stackView, false /* attachToRoot */);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index e5af3897dff2..4a1bbe48efb0 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -1459,7 +1459,7 @@ public class BubbleStackView extends FrameLayout {
mFlyout.setupFlyoutStartingAsDot(
updateMessage, mStackAnimationController.getStackPosition(), getWidth(),
mStackAnimationController.isStackOnLeftSide(),
- bubble.getIconView().getBadgeColor() /* dotColor */,
+ bubble.getIconView().getDotColor() /* dotColor */,
expandFlyoutAfterDelay /* onLayoutComplete */,
mFlyoutOnHide,
bubble.getIconView().getDotCenter());
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
index fe4fa90a272d..35657d38df0c 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
@@ -24,17 +24,16 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Path;
-import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
-import android.graphics.drawable.InsetDrawable;
import android.util.AttributeSet;
import android.util.PathParser;
import android.widget.FrameLayout;
import com.android.internal.graphics.ColorUtils;
+import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.ColorExtractor;
import com.android.launcher3.icons.ShadowGenerator;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -45,17 +44,13 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
*/
public class BubbleView extends FrameLayout {
- private static final int DARK_ICON_ALPHA = 180;
- private static final double ICON_MIN_CONTRAST = 4.1;
- private static final int DEFAULT_BACKGROUND_COLOR = Color.LTGRAY;
// Same value as Launcher3 badge code
private static final float WHITE_SCRIM_ALPHA = 0.54f;
private Context mContext;
private BadgedImageView mBadgedImageView;
- private int mBadgeColor;
- private int mIconInset;
- private Drawable mUserBadgedAppIcon;
+ private int mDotColor;
+ private ColorExtractor mColorExtractor;
// mBubbleIconFactory cannot be static because it depends on Context.
private BubbleIconFactory mBubbleIconFactory;
@@ -79,13 +74,13 @@ public class BubbleView extends FrameLayout {
public BubbleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mContext = context;
- mIconInset = getResources().getDimensionPixelSize(R.dimen.bubble_icon_inset);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mBadgedImageView = findViewById(R.id.bubble_image);
+ mColorExtractor = new ColorExtractor();
}
@Override
@@ -106,6 +101,13 @@ public class BubbleView extends FrameLayout {
}
/**
+ * @param factory Factory for creating normalized bubble icons.
+ */
+ public void setBubbleIconFactory(BubbleIconFactory factory) {
+ mBubbleIconFactory = factory;
+ }
+
+ /**
* The {@link NotificationEntry} associated with this view, if one exists.
*/
@Nullable
@@ -129,17 +131,6 @@ public class BubbleView extends FrameLayout {
updateViews();
}
- /**
- * @param factory Factory for creating normalized bubble icons.
- */
- public void setBubbleIconFactory(BubbleIconFactory factory) {
- mBubbleIconFactory = factory;
- }
-
- public void setAppIcon(Drawable appIcon) {
- mUserBadgedAppIcon = appIcon;
- }
-
/** Changes the dot's visibility to match the bubble view's state. */
void updateDotVisibility(boolean animate) {
updateDotVisibility(animate, null /* after */);
@@ -154,9 +145,17 @@ public class BubbleView extends FrameLayout {
updateDotVisibility(animate);
}
+ boolean isDotShowing() {
+ return mBubble.showBubbleDot() && !mSuppressDot;
+ }
+
+ int getDotColor() {
+ return mDotColor;
+ }
+
/** Sets the position of the 'new' dot, animating it out and back in if requested. */
void setDotPosition(boolean onLeft, boolean animate) {
- if (animate && onLeft != mBadgedImageView.getDotOnLeft() && shouldShowDot()) {
+ if (animate && onLeft != mBadgedImageView.getDotOnLeft() && isDotShowing()) {
animateDot(false /* showDot */, () -> {
mBadgedImageView.setDotOnLeft(onLeft);
animateDot(true /* showDot */, null);
@@ -180,7 +179,7 @@ public class BubbleView extends FrameLayout {
* after animation if requested.
*/
private void updateDotVisibility(boolean animate, Runnable after) {
- final boolean showDot = shouldShowDot();
+ final boolean showDot = isDotShowing();
if (animate) {
animateDot(showDot, after);
} else {
@@ -218,42 +217,21 @@ public class BubbleView extends FrameLayout {
if (mBubble == null || mBubbleIconFactory == null) {
return;
}
- // Update icon.
- Notification.BubbleMetadata metadata = mBubble.getEntry().getBubbleMetadata();
- Notification n = mBubble.getEntry().getSbn().getNotification();
- Icon ic = metadata.getIcon();
- boolean needsTint = ic.getType() != Icon.TYPE_ADAPTIVE_BITMAP;
-
- Drawable iconDrawable = ic.loadDrawable(mContext);
- if (needsTint) {
- iconDrawable = buildIconWithTint(iconDrawable, n.color);
- }
- Bitmap bubbleIcon = mBubbleIconFactory.createBadgedIconBitmap(iconDrawable,
- null /* user */,
- true /* shrinkNonAdaptiveIcons */).icon;
-
- // Give it a shadow
- Bitmap userBadgedBitmap = mBubbleIconFactory.createIconBitmap(mUserBadgedAppIcon,
- 1f, mBubbleIconFactory.getBadgeSize());
- Canvas c = new Canvas();
- ShadowGenerator shadowGenerator = new ShadowGenerator(mBubbleIconFactory.getBadgeSize());
- c.setBitmap(userBadgedBitmap);
- shadowGenerator.recreateIcon(Bitmap.createBitmap(userBadgedBitmap), c);
- mBubbleIconFactory.badgeWithDrawable(bubbleIcon,
- new BitmapDrawable(mContext.getResources(), userBadgedBitmap));
- mBadgedImageView.setImageBitmap(bubbleIcon);
+ Drawable bubbleDrawable = getBubbleDrawable(mContext);
+ BitmapInfo badgeBitmapInfo = getBadgedBitmap();
+ BitmapInfo bubbleBitmapInfo = getBubbleBitmap(bubbleDrawable, badgeBitmapInfo);
+ mBadgedImageView.setImageBitmap(bubbleBitmapInfo.icon);
// Update badge.
- int badgeColor = determineDominateColor(iconDrawable, n.color);
- mBadgeColor = badgeColor;
- mBadgedImageView.setDotColor(badgeColor);
+ mDotColor = ColorUtils.blendARGB(badgeBitmapInfo.color, Color.WHITE, WHITE_SCRIM_ALPHA);
+ mBadgedImageView.setDotColor(mDotColor);
// Update dot.
Path iconPath = PathParser.createPathFromPathData(
getResources().getString(com.android.internal.R.string.config_icon_mask));
Matrix matrix = new Matrix();
- float scale = mBubbleIconFactory.getNormalizer().getScale(iconDrawable,
+ float scale = mBubbleIconFactory.getNormalizer().getScale(bubbleDrawable,
null /* outBounds */, null /* path */, null /* outMaskShape */);
float radius = BadgedImageView.DEFAULT_PATH_SIZE / 2f;
matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
@@ -261,41 +239,34 @@ public class BubbleView extends FrameLayout {
iconPath.transform(matrix);
mBadgedImageView.drawDot(iconPath);
- animateDot(shouldShowDot(), null /* after */);
+ animateDot(isDotShowing(), null /* after */);
}
- boolean shouldShowDot() {
- return mBubble.showBubbleDot() && !mSuppressDot;
+ Drawable getBubbleDrawable(Context context) {
+ Notification.BubbleMetadata metadata = getEntry().getBubbleMetadata();
+ Icon ic = metadata.getIcon();
+ return ic.loadDrawable(context);
}
- int getBadgeColor() {
- return mBadgeColor;
- }
+ BitmapInfo getBadgedBitmap() {
+ Bitmap userBadgedBitmap = mBubbleIconFactory.createIconBitmap(
+ mBubble.getUserBadgedAppIcon(), 1f, mBubbleIconFactory.getBadgeSize());
- private AdaptiveIconDrawable buildIconWithTint(Drawable iconDrawable, int backgroundColor) {
- iconDrawable = checkTint(iconDrawable, backgroundColor);
- InsetDrawable foreground = new InsetDrawable(iconDrawable, mIconInset);
- ColorDrawable background = new ColorDrawable(backgroundColor);
- return new AdaptiveIconDrawable(background, foreground);
+ Canvas c = new Canvas();
+ ShadowGenerator shadowGenerator = new ShadowGenerator(mBubbleIconFactory.getBadgeSize());
+ c.setBitmap(userBadgedBitmap);
+ shadowGenerator.recreateIcon(Bitmap.createBitmap(userBadgedBitmap), c);
+ BitmapInfo bitmapInfo = mBubbleIconFactory.createIconBitmap(userBadgedBitmap);
+ return bitmapInfo;
}
- private Drawable checkTint(Drawable iconDrawable, int backgroundColor) {
- backgroundColor = ColorUtils.setAlphaComponent(backgroundColor, 255 /* alpha */);
- if (backgroundColor == Color.TRANSPARENT) {
- // ColorUtils throws exception when background is translucent.
- backgroundColor = DEFAULT_BACKGROUND_COLOR;
- }
- iconDrawable.setTint(Color.WHITE);
- double contrastRatio = ColorUtils.calculateContrast(Color.WHITE, backgroundColor);
- if (contrastRatio < ICON_MIN_CONTRAST) {
- int dark = ColorUtils.setAlphaComponent(Color.BLACK, DARK_ICON_ALPHA);
- iconDrawable.setTint(dark);
- }
- return iconDrawable;
- }
+ BitmapInfo getBubbleBitmap(Drawable bubble, BitmapInfo badge) {
+ BitmapInfo bubbleIconInfo = mBubbleIconFactory.createBadgedIconBitmap(bubble,
+ null /* user */,
+ true /* shrinkNonAdaptiveIcons */);
- private int determineDominateColor(Drawable d, int defaultTint) {
- // XXX: should we pull from the drawable, app icon, notif tint?
- return ColorUtils.blendARGB(defaultTint, Color.WHITE, WHITE_SCRIM_ALPHA);
+ mBubbleIconFactory.badgeWithDrawable(bubbleIconInfo.icon,
+ new BitmapDrawable(mContext.getResources(), badge.icon));
+ return bubbleIconInfo;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
index 3b0c9aebfe08..3cf14d65e5b8 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
@@ -16,109 +16,37 @@
package com.android.systemui.dagger;
-import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
-
-import android.content.Context;
-import android.os.PowerManager;
-import android.util.DisplayMetrics;
-
-import androidx.annotation.Nullable;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.ForegroundServiceController;
import com.android.systemui.LatencyTester;
import com.android.systemui.ScreenDecorations;
import com.android.systemui.SizeCompatModeActivityController;
import com.android.systemui.SliceBroadcastRelayHandler;
import com.android.systemui.SystemUI;
-import com.android.systemui.UiOffloadThread;
-import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.assist.AssistManager;
import com.android.systemui.biometrics.AuthController;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.bubbles.BubbleController;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.doze.DozeLog;
import com.android.systemui.globalactions.GlobalActionsComponent;
import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.pip.PipUI;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.power.PowerUI;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsModule;
-import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.FeatureFlags;
-import com.android.systemui.statusbar.NavigationBarController;
-import com.android.systemui.statusbar.NotificationListener;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.NotificationViewHierarchyManager;
-import com.android.systemui.statusbar.PulseExpansionHandler;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.VibratorHelper;
-import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
-import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.shortcut.ShortcutKeyDispatcher;
+import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.notification.InstantAppNotifier;
-import com.android.systemui.statusbar.notification.NewNotifPipeline;
-import com.android.systemui.statusbar.notification.NotificationAlertingManager;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
-import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.logging.NotifLog;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
-import com.android.systemui.statusbar.phone.AutoHideController;
-import com.android.systemui.statusbar.phone.BiometricUnlockController;
-import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.DozeScrimController;
-import com.android.systemui.statusbar.phone.DozeServiceHost;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.KeyguardLiftController;
-import com.android.systemui.statusbar.phone.LightBarController;
-import com.android.systemui.statusbar.phone.LockscreenWallpaper;
-import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
-import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.phone.StatusBarWindowController;
-import com.android.systemui.statusbar.phone.StatusBarWindowViewController;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
-import com.android.systemui.statusbar.policy.RemoteInputUriController;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.statusbar.phone.StatusBarModule;
import com.android.systemui.statusbar.tv.TvStatusBar;
import com.android.systemui.theme.ThemeOverlayController;
-import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.util.leak.GarbageMonitor;
import com.android.systemui.volume.VolumeUI;
-import javax.inject.Named;
-import javax.inject.Singleton;
-
import dagger.Binds;
-import dagger.Lazy;
import dagger.Module;
-import dagger.Provides;
import dagger.multibindings.ClassKey;
import dagger.multibindings.IntoMap;
/**
* SystemUI objects that are injectable should go here.
*/
-@Module(includes = {RecentsModule.class})
+@Module(includes = {RecentsModule.class, StatusBarModule.class})
public abstract class SystemUIBinder {
/** Inject into AuthController. */
@Binds
@@ -126,11 +54,17 @@ public abstract class SystemUIBinder {
@ClassKey(AuthController.class)
public abstract SystemUI bindAuthController(AuthController service);
+ /** Inject into Divider. */
+ @Binds
+ @IntoMap
+ @ClassKey(Divider.class)
+ public abstract SystemUI bindDivider(Divider sysui);
+
/** Inject into GarbageMonitor.Service. */
@Binds
@IntoMap
@ClassKey(GarbageMonitor.Service.class)
- public abstract SystemUI bindGarbageMonitorService(GarbageMonitor.Service service);
+ public abstract SystemUI bindGarbageMonitorService(GarbageMonitor.Service sysui);
/** Inject into GlobalActionsComponent. */
@Binds
@@ -180,6 +114,12 @@ public abstract class SystemUIBinder {
@ClassKey(ScreenDecorations.class)
public abstract SystemUI bindScreenDecorations(ScreenDecorations sysui);
+ /** Inject into ShortcutKeyDispatcher. */
+ @Binds
+ @IntoMap
+ @ClassKey(ShortcutKeyDispatcher.class)
+ public abstract SystemUI bindsShortcutKeyDispatcher(ShortcutKeyDispatcher sysui);
+
/** Inject into SizeCompatModeActivityController. */
@Binds
@IntoMap
@@ -216,148 +156,4 @@ public abstract class SystemUIBinder {
@IntoMap
@ClassKey(VolumeUI.class)
public abstract SystemUI bindVolumeUI(VolumeUI sysui);
-
- /**
- * Provides our instance of StatusBar which is considered optional.
- */
- @Provides
- @Singleton
- static StatusBar provideStatusBar(
- Context context,
- FeatureFlags featureFlags,
- LightBarController lightBarController,
- AutoHideController autoHideController,
- KeyguardUpdateMonitor keyguardUpdateMonitor,
- StatusBarIconController statusBarIconController,
- DozeLog dozeLog,
- InjectionInflationController injectionInflationController,
- PulseExpansionHandler pulseExpansionHandler,
- NotificationWakeUpCoordinator notificationWakeUpCoordinator,
- KeyguardBypassController keyguardBypassController,
- KeyguardStateController keyguardStateController,
- HeadsUpManagerPhone headsUpManagerPhone,
- DynamicPrivacyController dynamicPrivacyController,
- BypassHeadsUpNotifier bypassHeadsUpNotifier,
- @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
- Lazy<NewNotifPipeline> newNotifPipeline,
- FalsingManager falsingManager,
- BroadcastDispatcher broadcastDispatcher,
- RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
- NotificationGutsManager notificationGutsManager,
- NotificationLogger notificationLogger,
- NotificationEntryManager notificationEntryManager,
- NotificationInterruptionStateProvider notificationInterruptionStateProvider,
- NotificationViewHierarchyManager notificationViewHierarchyManager,
- ForegroundServiceController foregroundServiceController,
- AppOpsController appOpsController,
- KeyguardViewMediator keyguardViewMediator,
- ZenModeController zenModeController,
- NotificationAlertingManager notificationAlertingManager,
- DisplayMetrics displayMetrics,
- MetricsLogger metricsLogger,
- UiOffloadThread uiOffloadThread,
- NotificationMediaManager notificationMediaManager,
- NotificationLockscreenUserManager lockScreenUserManager,
- NotificationRemoteInputManager remoteInputManager,
- UserSwitcherController userSwitcherController,
- NetworkController networkController,
- BatteryController batteryController,
- SysuiColorExtractor colorExtractor,
- ScreenLifecycle screenLifecycle,
- WakefulnessLifecycle wakefulnessLifecycle,
- SysuiStatusBarStateController statusBarStateController,
- VibratorHelper vibratorHelper,
- BubbleController bubbleController,
- NotificationGroupManager groupManager,
- NotificationGroupAlertTransferHelper groupAlertTransferHelper,
- VisualStabilityManager visualStabilityManager,
- DeviceProvisionedController deviceProvisionedController,
- NavigationBarController navigationBarController,
- AssistManager assistManager,
- NotificationListener notificationListener,
- ConfigurationController configurationController,
- StatusBarWindowController statusBarWindowController,
- StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder,
- NotifLog notifLog,
- DozeParameters dozeParameters,
- ScrimController scrimController,
- @Nullable KeyguardLiftController keyguardLiftController,
- Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
- Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
- DozeServiceHost dozeServiceHost,
- PowerManager powerManager,
- DozeScrimController dozeScrimController,
- CommandQueue commandQueue,
- PluginManager pluginManager,
- RemoteInputUriController remoteInputUriController) {
- return new StatusBar(
- context,
- featureFlags,
- lightBarController,
- autoHideController,
- keyguardUpdateMonitor,
- statusBarIconController,
- dozeLog,
- injectionInflationController,
- pulseExpansionHandler,
- notificationWakeUpCoordinator,
- keyguardBypassController,
- keyguardStateController,
- headsUpManagerPhone,
- dynamicPrivacyController,
- bypassHeadsUpNotifier,
- allowNotificationLongPress,
- newNotifPipeline,
- falsingManager,
- broadcastDispatcher,
- remoteInputQuickSettingsDisabler,
- notificationGutsManager,
- notificationLogger,
- notificationEntryManager,
- notificationInterruptionStateProvider,
- notificationViewHierarchyManager,
- foregroundServiceController,
- appOpsController,
- keyguardViewMediator,
- zenModeController,
- notificationAlertingManager,
- displayMetrics,
- metricsLogger,
- uiOffloadThread,
- notificationMediaManager,
- lockScreenUserManager,
- remoteInputManager,
- userSwitcherController,
- networkController,
- batteryController,
- colorExtractor,
- screenLifecycle,
- wakefulnessLifecycle,
- statusBarStateController,
- vibratorHelper,
- bubbleController,
- groupManager,
- groupAlertTransferHelper,
- visualStabilityManager,
- deviceProvisionedController,
- navigationBarController,
- assistManager,
- notificationListener,
- configurationController,
- statusBarWindowController,
- statusBarWindowViewControllerBuilder,
- notifLog,
- dozeParameters,
- scrimController,
- keyguardLiftController,
- lockscreenWallpaperLazy,
- biometricUnlockControllerLazy,
- dozeServiceHost,
- powerManager,
- dozeScrimController,
- commandQueue,
- pluginManager,
- remoteInputUriController);
- }
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index 7b8d3bc4a121..f86aaf13e5bd 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -19,12 +19,18 @@ package com.android.systemui.dagger;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
+import android.content.Context;
+
import androidx.annotation.Nullable;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerImpl;
import com.android.systemui.power.EnhancedEstimates;
import com.android.systemui.power.EnhancedEstimatesImpl;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsImplementation;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.notification.collection.NotificationData;
@@ -77,4 +83,17 @@ abstract class SystemUIDefaultModule {
static boolean provideAllowNotificationLongPress() {
return true;
}
+
+ @Singleton
+ @Provides
+ static Divider provideDivider(Context context) {
+ return new Divider(context);
+ }
+
+ @Provides
+ @Singleton
+ static Recents provideRecents(Context context, RecentsImplementation recentsImplementation,
+ CommandQueue commandQueue) {
+ return new Recents(context, recentsImplementation, commandQueue);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 9e7f6c683bbe..6ae21b39f331 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -25,6 +25,9 @@ import com.android.systemui.DumpController;
import com.android.systemui.assist.AssistModule;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.notification.people.PeopleHubModule;
import com.android.systemui.statusbar.phone.KeyguardLiftController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -71,5 +74,14 @@ public abstract class SystemUIModule {
}
@BindsOptionalOf
+ abstract CommandQueue optionalCommandQueue();
+
+ @BindsOptionalOf
+ abstract Divider optionalDivider();
+
+ @BindsOptionalOf
+ abstract Recents optionalRecents();
+
+ @BindsOptionalOf
abstract StatusBar optionalStatusBar();
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index eaa72dc4fb8c..71e1593302c3 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -18,7 +18,6 @@ package com.android.systemui.doze;
import android.annotation.Nullable;
import android.app.AlarmManager;
-import android.app.Application;
import android.app.IWallpaperManager;
import android.content.Context;
import android.hardware.Sensor;
@@ -28,13 +27,13 @@ import android.os.Handler;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
-import com.android.systemui.SystemUIApplication;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.sensors.AsyncSensorManager;
import com.android.systemui.util.sensors.ProximitySensor;
@@ -60,6 +59,7 @@ public class DozeFactory {
private final Handler mHandler;
private final BiometricUnlockController mBiometricUnlockController;
private final BroadcastDispatcher mBroadcastDispatcher;
+ private final DozeServiceHost mDozeServiceHost;
@Inject
public DozeFactory(FalsingManager falsingManager, DozeLog dozeLog,
@@ -70,7 +70,7 @@ public class DozeFactory {
ProximitySensor proximitySensor,
DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler,
BiometricUnlockController biometricUnlockController,
- BroadcastDispatcher broadcastDispatcher) {
+ BroadcastDispatcher broadcastDispatcher, DozeServiceHost dozeServiceHost) {
mFalsingManager = falsingManager;
mDozeLog = dozeLog;
mDozeParameters = dozeParameters;
@@ -86,16 +86,16 @@ public class DozeFactory {
mHandler = handler;
mBiometricUnlockController = biometricUnlockController;
mBroadcastDispatcher = broadcastDispatcher;
+ mDozeServiceHost = dozeServiceHost;
}
/** Creates a DozeMachine with its parts for {@code dozeService}. */
DozeMachine assembleMachine(DozeService dozeService) {
- DozeHost host = getHost(dozeService);
AmbientDisplayConfiguration config = new AmbientDisplayConfiguration(dozeService);
WakeLock wakeLock = mDelayedWakeLockBuilder.setHandler(mHandler).setTag("Doze").build();
DozeMachine.Service wrappedService = dozeService;
- wrappedService = new DozeBrightnessHostForwarder(wrappedService, host);
+ wrappedService = new DozeBrightnessHostForwarder(wrappedService, mDozeServiceHost);
wrappedService = DozeScreenStatePreventingAdapter.wrapIfNeeded(
wrappedService, mDozeParameters);
wrappedService = DozeSuspendScreenStatePreventingAdapter.wrapIfNeeded(
@@ -106,16 +106,19 @@ public class DozeFactory {
machine.setParts(new DozeMachine.Part[]{
new DozePauser(mHandler, machine, mAlarmManager, mDozeParameters.getPolicy()),
new DozeFalsingManagerAdapter(mFalsingManager),
- createDozeTriggers(dozeService, mAsyncSensorManager, host, mAlarmManager, config,
- mDozeParameters, mHandler, wakeLock, machine, mDockManager, mDozeLog),
- createDozeUi(dozeService, host, wakeLock, machine, mHandler, mAlarmManager,
- mDozeParameters, mDozeLog),
- new DozeScreenState(wrappedService, mHandler, host, mDozeParameters, wakeLock),
- createDozeScreenBrightness(dozeService, wrappedService, mAsyncSensorManager, host,
- mDozeParameters, mHandler),
- new DozeWallpaperState(
- mWallpaperManager, mBiometricUnlockController, mDozeParameters),
- new DozeDockHandler(dozeService, machine, host, config, mHandler, mDockManager),
+ createDozeTriggers(dozeService, mAsyncSensorManager, mDozeServiceHost,
+ mAlarmManager, config, mDozeParameters, mHandler, wakeLock, machine,
+ mDockManager, mDozeLog),
+ createDozeUi(dozeService, mDozeServiceHost, wakeLock, machine, mHandler,
+ mAlarmManager, mDozeParameters, mDozeLog),
+ new DozeScreenState(wrappedService, mHandler, mDozeServiceHost, mDozeParameters,
+ wakeLock),
+ createDozeScreenBrightness(dozeService, wrappedService, mAsyncSensorManager,
+ mDozeServiceHost, mDozeParameters, mHandler),
+ new DozeWallpaperState(mWallpaperManager, mBiometricUnlockController,
+ mDozeParameters),
+ new DozeDockHandler(dozeService, machine, mDozeServiceHost, config, mHandler,
+ mDockManager),
new DozeAuthRemover(dozeService)
});
@@ -148,10 +151,4 @@ public class DozeFactory {
return new DozeUi(context, alarmManager, machine, wakeLock, host, handler, params,
mKeyguardUpdateMonitor, dozeLog);
}
-
- public static DozeHost getHost(DozeService service) {
- Application appCandidate = service.getApplication();
- final SystemUIApplication app = (SystemUIApplication) appCandidate;
- return app.getComponent(DozeHost.class);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 08734d27ba55..7cbbdd783e74 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -55,10 +55,6 @@ public class DozeService extends DreamService
setWindowless(true);
- if (DozeFactory.getHost(this) == null) {
- finish();
- return;
- }
mPluginManager.addPluginListener(this, DozeServicePlugin.class, false /* allowMultiple */);
mDozeMachine = mDozeFactory.assembleMachine(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
index 86c532cdb773..ca04633b316a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
@@ -117,9 +117,14 @@ public class WorkLockActivity extends Activity {
}
}
+ @VisibleForTesting
+ protected void unregisterBroadcastReceiver() {
+ mBroadcastDispatcher.unregisterReceiver(mLockEventReceiver);
+ }
+
@Override
public void onDestroy() {
- unregisterReceiver(mLockEventReceiver);
+ unregisterBroadcastReceiver();
super.onDestroy();
}
@@ -170,7 +175,12 @@ public class WorkLockActivity extends Activity {
credential.putExtra(EXTRA_FROM_WORK_LOCK_ACTIVITY, true);
}
- startActivityForResult(credential, REQUEST_CODE_CONFIRM_CREDENTIALS);
+ final ActivityOptions launchOptions = ActivityOptions.makeBasic();
+ launchOptions.setLaunchTaskId(getTaskId());
+ launchOptions.setTaskOverlay(true /* taskOverlay */, true /* canResume */);
+
+ startActivityForResult(credential, REQUEST_CODE_CONFIRM_CREDENTIALS,
+ launchOptions.toBundle());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
index 7f11e56ba168..60bc6b6855e6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
@@ -57,8 +57,8 @@ public class OverviewProxyRecentsImpl implements RecentsImplementation {
private final static String TAG = "OverviewProxyRecentsImpl";
@Nullable
private final Lazy<StatusBar> mStatusBarLazy;
+ private final Optional<Divider> mDividerOptional;
- private SysUiServiceProvider mSysUiServiceProvider;
private Context mContext;
private Handler mHandler;
private TrustManager mTrustManager;
@@ -66,14 +66,15 @@ public class OverviewProxyRecentsImpl implements RecentsImplementation {
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
@Inject
- public OverviewProxyRecentsImpl(Optional<Lazy<StatusBar>> statusBarLazy) {
+ public OverviewProxyRecentsImpl(Optional<Lazy<StatusBar>> statusBarLazy,
+ Optional<Divider> dividerOptional) {
mStatusBarLazy = statusBarLazy.orElse(null);
+ mDividerOptional = dividerOptional;
}
@Override
public void onStart(Context context, SysUiServiceProvider sysUiServiceProvider) {
mContext = context;
- mSysUiServiceProvider = sysUiServiceProvider;
mHandler = new Handler();
mTrustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
@@ -164,10 +165,8 @@ public class OverviewProxyRecentsImpl implements RecentsImplementation {
runningTask.id, stackCreateMode, initialBounds)) {
// The overview service is handling split screen, so just skip the wait for the
// first draw and notify the divider to start animating now
- final Divider divider = mSysUiServiceProvider.getComponent(Divider.class);
- if (divider != null) {
- divider.onRecentsDrawn();
- }
+ mDividerOptional.ifPresent(Divider::onRecentsDrawn);
+
return true;
}
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 3fc139882693..ba9fc3da10df 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -80,6 +80,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -102,6 +103,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
private final Context mContext;
private final PipUI mPipUI;
+ private final Optional<Divider> mDividerOptional;
private SysUiState mSysUiState;
private final Handler mHandler;
private final NavigationBarController mNavBarController;
@@ -208,10 +210,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
}
long token = Binder.clearCallingIdentity();
try {
- Divider divider = SysUiServiceProvider.getComponent(mContext, Divider.class);
- if (divider != null) {
- divider.onDockedFirstAnimationFrame();
- }
+ mDividerOptional.ifPresent(Divider::onDockedFirstAnimationFrame);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -241,11 +240,9 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
}
long token = Binder.clearCallingIdentity();
try {
- Divider divider = SysUiServiceProvider.getComponent(mContext, Divider.class);
- if (divider != null) {
- return divider.getView().getNonMinimizedSplitScreenSecondaryBounds();
- }
- return null;
+ return mDividerOptional.map(
+ divider -> divider.getView().getNonMinimizedSplitScreenSecondaryBounds())
+ .orElse(null);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -475,11 +472,12 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
private final IBinder.DeathRecipient mOverviewServiceDeathRcpt
= this::cleanupAfterDeath;
+ @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
@Inject
public OverviewProxyService(Context context, DeviceProvisionedController provisionController,
NavigationBarController navBarController, NavigationModeController navModeController,
- StatusBarWindowController statusBarWinController,
- SysUiState sysUiState, PipUI pipUI) {
+ StatusBarWindowController statusBarWinController, SysUiState sysUiState, PipUI pipUI,
+ Optional<Divider> dividerOptional) {
mContext = context;
mPipUI = pipUI;
mHandler = new Handler();
@@ -487,6 +485,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
mStatusBarWinController = statusBarWinController;
mDeviceProvisionedController = provisionController;
mConnectionBackoffAttempts = 0;
+ mDividerOptional = dividerOptional;
mRecentsComponentName = ComponentName.unflattenFromString(context.getString(
com.android.internal.R.string.config_recentsComponentName));
mQuickStepIntent = new Intent(ACTION_QUICKSTEP)
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index a8ecc1275221..882930bc1049 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -28,19 +28,14 @@ import com.android.systemui.statusbar.CommandQueue;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
/**
* A proxy to a Recents implementation.
*/
-@Singleton
public class Recents extends SystemUI implements CommandQueue.Callbacks {
private final RecentsImplementation mImpl;
private final CommandQueue mCommandQueue;
- @Inject
public Recents(Context context, RecentsImplementation impl, CommandQueue commandQueue) {
super(context);
mImpl = impl;
@@ -50,7 +45,6 @@ public class Recents extends SystemUI implements CommandQueue.Callbacks {
@Override
public void start() {
mCommandQueue.addCallback(this);
- putComponent(Recents.class, this);
mImpl.onStart(mContext, this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 264d644f9057..3ff6d0d2278d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -17,13 +17,11 @@
package com.android.systemui.screenshot;
import static android.content.Context.NOTIFICATION_SERVICE;
+import static android.os.AsyncTask.THREAD_POOL_EXECUTOR;
import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_CORNER_FLOW;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ACTION_INTENT;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_CANCEL_NOTIFICATION;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_DISALLOW_ENTER_PIP;
import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_SCREENSHOT;
import android.animation.Animator;
@@ -32,7 +30,9 @@ import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.ActivityOptions;
+import android.app.ActivityTaskManager;
import android.app.Notification;
import android.app.Notification.BigPictureStyle;
import android.app.NotificationManager;
@@ -45,6 +45,7 @@ import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -67,7 +68,10 @@ import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.Process;
+import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.DeviceConfig;
import android.provider.MediaStore;
import android.text.TextUtils;
@@ -85,9 +89,12 @@ import android.view.animation.Interpolator;
import android.widget.ImageView;
import android.widget.Toast;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.dagger.qualifiers.MainResources;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -100,7 +107,11 @@ import java.io.IOException;
import java.io.OutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.util.Collections;
import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -109,372 +120,423 @@ import java.util.function.Function;
import javax.inject.Inject;
import javax.inject.Singleton;
+import dagger.Lazy;
/**
- * POD used in the AsyncTask which saves an image in the background.
+ * Class for handling device screen shots
*/
-class SaveImageInBackgroundData {
- Context context;
- Bitmap image;
- Uri imageUri;
- Runnable finisher;
- Function<PendingIntent, Void> onEditReady;
- int iconSize;
- int previewWidth;
- int previewheight;
- int errorMsgResId;
-
- void clearImage() {
- image = null;
- imageUri = null;
- iconSize = 0;
- }
- void clearContext() {
- context = null;
+@Singleton
+public class GlobalScreenshot {
+
+ /**
+ * POD used in the AsyncTask which saves an image in the background.
+ */
+ private static class SaveImageInBackgroundData {
+ public Context context;
+ public Bitmap image;
+ public Uri imageUri;
+ public Runnable finisher;
+ public Function<PendingIntent, Void> onEditReady;
+ public int iconSize;
+ public int previewWidth;
+ public int previewheight;
+ public int errorMsgResId;
+
+ void clearImage() {
+ image = null;
+ imageUri = null;
+ iconSize = 0;
+ }
+ void clearContext() {
+ context = null;
+ }
}
-}
-/**
- * An AsyncTask that saves an image to the media store in the background.
- */
-class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
- private static final String TAG = "SaveImageInBackgroundTask";
-
- private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
- private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";
-
- private final SaveImageInBackgroundData mParams;
- private final NotificationManager mNotificationManager;
- private final Notification.Builder mNotificationBuilder, mPublicNotificationBuilder;
- private final String mImageFileName;
- private final long mImageTime;
- private final BigPictureStyle mNotificationStyle;
- private final int mImageWidth;
- private final int mImageHeight;
-
- SaveImageInBackgroundTask(Context context, SaveImageInBackgroundData data,
- NotificationManager nManager) {
- Resources r = context.getResources();
+ /**
+ * An AsyncTask that saves an image to the media store in the background.
+ */
+ private static class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
+ private static final String TAG = "SaveImageInBackgroundTask";
+
+ private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
+ private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";
+
+ private final SaveImageInBackgroundData mParams;
+ private final NotificationManager mNotificationManager;
+ private final Notification.Builder mNotificationBuilder, mPublicNotificationBuilder;
+ private final String mImageFileName;
+ private final long mImageTime;
+ private final BigPictureStyle mNotificationStyle;
+ private final int mImageWidth;
+ private final int mImageHeight;
+ private final Handler mHandler;
+ private final ScreenshotNotificationSmartActionsProvider mSmartActionsProvider;
+
+ SaveImageInBackgroundTask(Context context, SaveImageInBackgroundData data,
+ NotificationManager nManager) {
+ Resources r = context.getResources();
+
+ // Prepare all the output metadata
+ mParams = data;
+ mImageTime = System.currentTimeMillis();
+ String imageDate = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(mImageTime));
+ mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, imageDate);
+
+ // Initialize screenshot notification smart actions provider.
+ mHandler = new Handler();
+ mSmartActionsProvider =
+ SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider();
+
+ // Create the large notification icon
+ mImageWidth = data.image.getWidth();
+ mImageHeight = data.image.getHeight();
+ int iconSize = data.iconSize;
+ int previewWidth = data.previewWidth;
+ int previewHeight = data.previewheight;
+
+ Paint paint = new Paint();
+ ColorMatrix desat = new ColorMatrix();
+ desat.setSaturation(0.25f);
+ paint.setColorFilter(new ColorMatrixColorFilter(desat));
+ Matrix matrix = new Matrix();
+ int overlayColor = 0x40FFFFFF;
+
+ matrix.setTranslate((previewWidth - mImageWidth) / 2,
+ (previewHeight - mImageHeight) / 2);
+ Bitmap picture = generateAdjustedHwBitmap(data.image, previewWidth, previewHeight,
+ matrix, paint, overlayColor);
+
+ // Note, we can't use the preview for the small icon, since it is non-square
+ float scale = (float) iconSize / Math.min(mImageWidth, mImageHeight);
+ matrix.setScale(scale, scale);
+ matrix.postTranslate((iconSize - (scale * mImageWidth)) / 2,
+ (iconSize - (scale * mImageHeight)) / 2);
+ Bitmap icon = generateAdjustedHwBitmap(data.image, iconSize, iconSize, matrix, paint,
+ overlayColor);
+
+ mNotificationManager = nManager;
+ final long now = System.currentTimeMillis();
+
+ // Setup the notification
+ mNotificationStyle = new Notification.BigPictureStyle()
+ .bigPicture(picture.createAshmemBitmap());
+
+ // The public notification will show similar info but with the actual screenshot omitted
+ mPublicNotificationBuilder =
+ new Notification.Builder(context, NotificationChannels.SCREENSHOTS_HEADSUP)
+ .setContentTitle(r.getString(R.string.screenshot_saving_title))
+ .setSmallIcon(R.drawable.stat_notify_image)
+ .setCategory(Notification.CATEGORY_PROGRESS)
+ .setWhen(now)
+ .setShowWhen(true)
+ .setColor(r.getColor(
+ com.android.internal.R.color.system_notification_accent_color));
+ SystemUI.overrideNotificationAppName(context, mPublicNotificationBuilder, true);
+
+ mNotificationBuilder = new Notification.Builder(context,
+ NotificationChannels.SCREENSHOTS_HEADSUP)
+ .setContentTitle(r.getString(R.string.screenshot_saving_title))
+ .setSmallIcon(R.drawable.stat_notify_image)
+ .setWhen(now)
+ .setShowWhen(true)
+ .setColor(r.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setStyle(mNotificationStyle)
+ .setPublicVersion(mPublicNotificationBuilder.build());
+ mNotificationBuilder.setFlag(Notification.FLAG_NO_CLEAR, true);
+ SystemUI.overrideNotificationAppName(context, mNotificationBuilder, true);
+
+ mNotificationManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT,
+ mNotificationBuilder.build());
+
+ /**
+ * NOTE: The following code prepares the notification builder for updating the
+ * notification after the screenshot has been written to disk.
+ */
+
+ // On the tablet, the large icon makes the notification appear as if it is clickable
+ // (and on small devices, the large icon is not shown) so defer showing the large icon
+ // until we compose the final post-save notification below.
+ mNotificationBuilder.setLargeIcon(icon.createAshmemBitmap());
+ // But we still don't set it for the expanded view, allowing the smallIcon to show here.
+ mNotificationStyle.bigLargeIcon((Bitmap) null);
+ }
- // Prepare all the output metadata
- mParams = data;
- mImageTime = System.currentTimeMillis();
- String imageDate = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(mImageTime));
- mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, imageDate);
-
- // Create the large notification icon
- mImageWidth = data.image.getWidth();
- mImageHeight = data.image.getHeight();
- int iconSize = data.iconSize;
- int previewWidth = data.previewWidth;
- int previewHeight = data.previewheight;
-
- Paint paint = new Paint();
- ColorMatrix desat = new ColorMatrix();
- desat.setSaturation(0.25f);
- paint.setColorFilter(new ColorMatrixColorFilter(desat));
- Matrix matrix = new Matrix();
- int overlayColor = 0x40FFFFFF;
-
- matrix.setTranslate((previewWidth - mImageWidth) / 2, (previewHeight - mImageHeight) / 2);
- Bitmap picture = generateAdjustedHwBitmap(data.image, previewWidth, previewHeight, matrix,
- paint, overlayColor);
-
- // Note, we can't use the preview for the small icon, since it is non-square
- float scale = (float) iconSize / Math.min(mImageWidth, mImageHeight);
- matrix.setScale(scale, scale);
- matrix.postTranslate((iconSize - (scale * mImageWidth)) / 2,
- (iconSize - (scale * mImageHeight)) / 2);
- Bitmap icon = generateAdjustedHwBitmap(data.image, iconSize, iconSize, matrix, paint,
- overlayColor);
-
- mNotificationManager = nManager;
- final long now = System.currentTimeMillis();
-
- // Setup the notification
- mNotificationStyle = new Notification.BigPictureStyle()
- .bigPicture(picture.createAshmemBitmap());
-
- // The public notification will show similar info but with the actual screenshot omitted
- mPublicNotificationBuilder =
- new Notification.Builder(context, NotificationChannels.SCREENSHOTS_HEADSUP)
- .setContentTitle(r.getString(R.string.screenshot_saving_title))
- .setSmallIcon(R.drawable.stat_notify_image)
- .setCategory(Notification.CATEGORY_PROGRESS)
- .setWhen(now)
- .setShowWhen(true)
- .setColor(r.getColor(
- com.android.internal.R.color.system_notification_accent_color));
- SystemUI.overrideNotificationAppName(context, mPublicNotificationBuilder, true);
-
- mNotificationBuilder = new Notification.Builder(context,
- NotificationChannels.SCREENSHOTS_HEADSUP)
- .setContentTitle(r.getString(R.string.screenshot_saving_title))
- .setSmallIcon(R.drawable.stat_notify_image)
- .setWhen(now)
- .setShowWhen(true)
- .setColor(r.getColor(com.android.internal.R.color.system_notification_accent_color))
- .setStyle(mNotificationStyle)
- .setPublicVersion(mPublicNotificationBuilder.build());
- mNotificationBuilder.setFlag(Notification.FLAG_NO_CLEAR, true);
- SystemUI.overrideNotificationAppName(context, mNotificationBuilder, true);
-
- mNotificationManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT,
- mNotificationBuilder.build());
+ private int getUserHandleOfForegroundApplication(Context context) {
+ // This logic matches
+ // com.android.systemui.statusbar.phone.PhoneStatusBarPolicy#updateManagedProfile
+ try {
+ return ActivityTaskManager.getService().getLastResumedActivityUserId();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "getUserHandleOfForegroundApplication: ", e);
+ return context.getUserId();
+ }
+ }
+
+ private boolean isManagedProfile(Context context) {
+ UserManager manager = UserManager.get(context);
+ UserInfo info = manager.getUserInfo(getUserHandleOfForegroundApplication(context));
+ return info.isManagedProfile();
+ }
/**
- * NOTE: The following code prepares the notification builder for updating the notification
- * after the screenshot has been written to disk.
+ * Generates a new hardware bitmap with specified values, copying the content from the
+ * passed in bitmap.
*/
+ private Bitmap generateAdjustedHwBitmap(Bitmap bitmap, int width, int height, Matrix matrix,
+ Paint paint, int color) {
+ Picture picture = new Picture();
+ Canvas canvas = picture.beginRecording(width, height);
+ canvas.drawColor(color);
+ canvas.drawBitmap(bitmap, matrix, paint);
+ picture.endRecording();
+ return Bitmap.createBitmap(picture);
+ }
- // On the tablet, the large icon makes the notification appear as if it is clickable (and
- // on small devices, the large icon is not shown) so defer showing the large icon until
- // we compose the final post-save notification below.
- mNotificationBuilder.setLargeIcon(icon.createAshmemBitmap());
- // But we still don't set it for the expanded view, allowing the smallIcon to show here.
- mNotificationStyle.bigLargeIcon((Bitmap) null);
- }
-
- /**
- * Generates a new hardware bitmap with specified values, copying the content from the passed
- * in bitmap.
- */
- private Bitmap generateAdjustedHwBitmap(Bitmap bitmap, int width, int height, Matrix matrix,
- Paint paint, int color) {
- Picture picture = new Picture();
- Canvas canvas = picture.beginRecording(width, height);
- canvas.drawColor(color);
- canvas.drawBitmap(bitmap, matrix, paint);
- picture.endRecording();
- return Bitmap.createBitmap(picture);
- }
+ @Override
+ protected Void doInBackground(Void... paramsUnused) {
+ if (isCancelled()) {
+ return null;
+ }
- @Override
- protected Void doInBackground(Void... paramsUnused) {
- if (isCancelled()) {
- return null;
- }
+ // By default, AsyncTask sets the worker thread to have background thread priority,
+ // so bump it back up so that we save a little quicker.
+ Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
- // By default, AsyncTask sets the worker thread to have background thread priority, so bump
- // it back up so that we save a little quicker.
- Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
+ Context context = mParams.context;
+ Bitmap image = mParams.image;
+ boolean smartActionsEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.ENABLE_SCREENSHOT_NOTIFICATION_SMART_ACTIONS, true);
+ CompletableFuture<List<Notification.Action>> smartActionsFuture = getSmartActionsFuture(
+ context, image, mSmartActionsProvider, mHandler, smartActionsEnabled,
+ isManagedProfile(context));
- Context context = mParams.context;
- Bitmap image = mParams.image;
- Resources r = context.getResources();
+ Resources r = context.getResources();
- try {
- // Save the screenshot to the MediaStore
- final MediaStore.PendingParams params = new MediaStore.PendingParams(
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mImageFileName, "image/png");
- params.setRelativePath(Environment.DIRECTORY_PICTURES + File.separator
- + Environment.DIRECTORY_SCREENSHOTS);
-
- final Uri uri = MediaStore.createPending(context, params);
- final MediaStore.PendingSession session = MediaStore.openPending(context, uri);
try {
- try (OutputStream out = session.openOutputStream()) {
- if (!image.compress(Bitmap.CompressFormat.PNG, 100, out)) {
- throw new IOException("Failed to compress");
+ // Save the screenshot to the MediaStore
+ final MediaStore.PendingParams params = new MediaStore.PendingParams(
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mImageFileName, "image/png");
+ params.setRelativePath(Environment.DIRECTORY_PICTURES + File.separator
+ + Environment.DIRECTORY_SCREENSHOTS);
+
+ final Uri uri = MediaStore.createPending(context, params);
+ final MediaStore.PendingSession session = MediaStore.openPending(context, uri);
+ try {
+ try (OutputStream out = session.openOutputStream()) {
+ if (!image.compress(Bitmap.CompressFormat.PNG, 100, out)) {
+ throw new IOException("Failed to compress");
+ }
+ }
+ session.publish();
+ } catch (Exception e) {
+ session.abandon();
+ throw e;
+ } finally {
+ IoUtils.closeQuietly(session);
+ }
+
+ // Note: Both the share and edit actions are proxied through ActionProxyReceiver in
+ // order to do some common work like dismissing the keyguard and sending
+ // closeSystemWindows
+
+ // Create a share intent, this will always go through the chooser activity first
+ // which should not trigger auto-enter PiP
+ String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
+ String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
+ Intent sharingIntent = new Intent(Intent.ACTION_SEND);
+ sharingIntent.setType("image/png");
+ sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
+ // Include URI in ClipData also, so that grantPermission picks it up.
+ // We don't use setData here because some apps interpret this as "to:".
+ ClipData clipdata = new ClipData(new ClipDescription("content",
+ new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
+ new ClipData.Item(uri));
+ sharingIntent.setClipData(clipdata);
+ sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
+ sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ // Make sure pending intents for the system user are still unique across users
+ // by setting the (otherwise unused) request code to the current user id.
+ int requestCode = context.getUserId();
+
+ PendingIntent chooserAction = PendingIntent.getBroadcast(context, requestCode,
+ new Intent(context, GlobalScreenshot.TargetChosenReceiver.class),
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
+ Intent sharingChooserIntent = Intent.createChooser(sharingIntent, null,
+ chooserAction.getIntentSender())
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ // Create a share action for the notification
+ PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
+ new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
+ .putExtra(EXTRA_ACTION_INTENT, sharingChooserIntent)
+ .putExtra(EXTRA_DISALLOW_ENTER_PIP, true)
+ .setAction(Intent.ACTION_SEND),
+ PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
+ Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
+ R.drawable.ic_screenshot_share,
+ r.getString(com.android.internal.R.string.share), shareAction);
+ mNotificationBuilder.addAction(shareActionBuilder.build());
+
+ // Create an edit intent, if a specific package is provided as the editor, then
+ // launch that directly
+ String editorPackage = context.getString(R.string.config_screenshotEditor);
+ Intent editIntent = new Intent(Intent.ACTION_EDIT);
+ if (!TextUtils.isEmpty(editorPackage)) {
+ editIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
+ }
+ editIntent.setType("image/png");
+ editIntent.setData(uri);
+ editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ editIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+ // Create a edit action
+ PendingIntent editAction = PendingIntent.getBroadcastAsUser(context, requestCode,
+ new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
+ .putExtra(EXTRA_ACTION_INTENT, editIntent)
+ .putExtra(EXTRA_CANCEL_NOTIFICATION,
+ editIntent.getComponent() != null)
+ .setAction(Intent.ACTION_EDIT),
+ PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
+ Notification.Action.Builder editActionBuilder = new Notification.Action.Builder(
+ R.drawable.ic_screenshot_edit,
+ r.getString(com.android.internal.R.string.screenshot_edit), editAction);
+ mNotificationBuilder.addAction(editActionBuilder.build());
+ if (editAction != null && mParams.onEditReady != null) {
+ mParams.onEditReady.apply(editAction);
+ }
+
+ // Create a delete action for the notification
+ PendingIntent deleteAction = PendingIntent.getBroadcast(context, requestCode,
+ new Intent(context, GlobalScreenshot.DeleteScreenshotReceiver.class)
+ .putExtra(GlobalScreenshot.SCREENSHOT_URI_ID, uri.toString()),
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
+ Notification.Action.Builder deleteActionBuilder = new Notification.Action.Builder(
+ R.drawable.ic_screenshot_delete,
+ r.getString(com.android.internal.R.string.delete), deleteAction);
+ mNotificationBuilder.addAction(deleteActionBuilder.build());
+
+ mParams.imageUri = uri;
+ mParams.image = null;
+ mParams.errorMsgResId = 0;
+
+ if (smartActionsEnabled) {
+ int timeoutMs = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags
+ .SCREENSHOT_NOTIFICATION_SMART_ACTIONS_TIMEOUT_MS,
+ 1000);
+ List<Notification.Action> smartActions = getSmartActions(smartActionsFuture,
+ timeoutMs);
+ for (Notification.Action action : smartActions) {
+ mNotificationBuilder.addAction(action);
}
}
- session.publish();
} catch (Exception e) {
- session.abandon();
- throw e;
- } finally {
- IoUtils.closeQuietly(session);
+ // IOException/UnsupportedOperationException may be thrown if external storage is
+ // not mounted
+ Slog.e(TAG, "unable to save screenshot", e);
+ mParams.clearImage();
+ mParams.errorMsgResId = R.string.screenshot_failed_to_save_text;
}
- // Note: Both the share and edit actions are proxied through ActionProxyReceiver in
- // order to do some common work like dismissing the keyguard and sending
- // closeSystemWindows
-
- // Create a share intent, this will always go through the chooser activity first which
- // should not trigger auto-enter PiP
- String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
- String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
- Intent sharingIntent = new Intent(Intent.ACTION_SEND);
- sharingIntent.setType("image/png");
- sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
- // Include URI in ClipData also, so that grantPermission picks it up.
- // We don't use setData here because some apps interpret this as "to:".
- ClipData clipdata = new ClipData(new ClipDescription("content",
- new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
- new ClipData.Item(uri));
- sharingIntent.setClipData(clipdata);
- sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
- sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- // Make sure pending intents for the system user are still unique across users
- // by setting the (otherwise unused) request code to the current user id.
- int requestCode = context.getUserId();
-
- PendingIntent chooserAction = PendingIntent.getBroadcast(context, requestCode,
- new Intent(context, GlobalScreenshot.TargetChosenReceiver.class),
- PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
- Intent sharingChooserIntent = Intent.createChooser(sharingIntent, null,
- chooserAction.getIntentSender())
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
- .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- // Create a share action for the notification
- PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
- new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
- .putExtra(EXTRA_ACTION_INTENT, sharingChooserIntent)
- .putExtra(EXTRA_DISALLOW_ENTER_PIP, true)
- .setAction(Intent.ACTION_SEND),
- PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
- Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
- R.drawable.ic_screenshot_share,
- r.getString(com.android.internal.R.string.share), shareAction);
- mNotificationBuilder.addAction(shareActionBuilder.build());
-
- // Create an edit intent, if a specific package is provided as the editor, then launch
- // that directly
- String editorPackage = context.getString(R.string.config_screenshotEditor);
- Intent editIntent = new Intent(Intent.ACTION_EDIT);
- if (!TextUtils.isEmpty(editorPackage)) {
- editIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
- }
- editIntent.setType("image/png");
- editIntent.setData(uri);
- editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- editIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-
- // Create a edit action
- PendingIntent editAction = PendingIntent.getBroadcastAsUser(context, requestCode,
- new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
- .putExtra(EXTRA_ACTION_INTENT, editIntent)
- .putExtra(EXTRA_CANCEL_NOTIFICATION, editIntent.getComponent() != null)
- .setAction(Intent.ACTION_EDIT),
- PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
- Notification.Action.Builder editActionBuilder = new Notification.Action.Builder(
- R.drawable.ic_screenshot_edit,
- r.getString(com.android.internal.R.string.screenshot_edit), editAction);
- mNotificationBuilder.addAction(editActionBuilder.build());
- if (editAction != null && mParams.onEditReady != null) {
- mParams.onEditReady.apply(editAction);
+ // Recycle the bitmap data
+ if (image != null) {
+ image.recycle();
}
- // Create a delete action for the notification
- PendingIntent deleteAction = PendingIntent.getBroadcast(context, requestCode,
- new Intent(context, GlobalScreenshot.DeleteScreenshotReceiver.class)
- .putExtra(GlobalScreenshot.SCREENSHOT_URI_ID, uri.toString()),
- PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
- Notification.Action.Builder deleteActionBuilder = new Notification.Action.Builder(
- R.drawable.ic_screenshot_delete,
- r.getString(com.android.internal.R.string.delete), deleteAction);
- mNotificationBuilder.addAction(deleteActionBuilder.build());
-
- mParams.imageUri = uri;
- mParams.image = null;
- mParams.errorMsgResId = 0;
- } catch (Exception e) {
- // IOException/UnsupportedOperationException may be thrown if external storage is not
- // mounted
- Slog.e(TAG, "unable to save screenshot", e);
- mParams.clearImage();
- mParams.errorMsgResId = R.string.screenshot_failed_to_save_text;
- }
-
- // Recycle the bitmap data
- if (image != null) {
- image.recycle();
+ return null;
}
- return null;
- }
-
- @Override
- protected void onPostExecute(Void params) {
- if (mParams.errorMsgResId != 0) {
- // Show a message that we've failed to save the image to disk
- GlobalScreenshot.notifyScreenshotError(mParams.context, mNotificationManager,
- mParams.errorMsgResId);
- } else {
- if (mParams.onEditReady != null) {
- // Cancel the "saving screenshot" notification
- mNotificationManager.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
+ @Override
+ protected void onPostExecute(Void params) {
+ if (mParams.errorMsgResId != 0) {
+ // Show a message that we've failed to save the image to disk
+ GlobalScreenshot.notifyScreenshotError(mParams.context, mNotificationManager,
+ mParams.errorMsgResId);
} else {
- // Show the final notification to indicate screenshot saved
- Context context = mParams.context;
- Resources r = context.getResources();
-
- // Create the intent to show the screenshot in gallery
- Intent launchIntent = new Intent(Intent.ACTION_VIEW);
- launchIntent.setDataAndType(mParams.imageUri, "image/png");
- launchIntent.setFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- final long now = System.currentTimeMillis();
-
- // Update the text and the icon for the existing notification
- mPublicNotificationBuilder
- .setContentTitle(r.getString(R.string.screenshot_saved_title))
- .setContentText(r.getString(R.string.screenshot_saved_text))
- .setContentIntent(
- PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
- .setWhen(now)
- .setAutoCancel(true)
- .setColor(context.getColor(
- com.android.internal.R.color.system_notification_accent_color));
- mNotificationBuilder
- .setContentTitle(r.getString(R.string.screenshot_saved_title))
- .setContentText(r.getString(R.string.screenshot_saved_text))
- .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
- .setWhen(now)
- .setAutoCancel(true)
- .setColor(context.getColor(
- com.android.internal.R.color.system_notification_accent_color))
- .setPublicVersion(mPublicNotificationBuilder.build())
- .setFlag(Notification.FLAG_NO_CLEAR, false);
-
- mNotificationManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT,
- mNotificationBuilder.build());
+ if (mParams.onEditReady != null) {
+ // Cancel the "saving screenshot" notification
+ mNotificationManager.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
+ } else {
+ // Show the final notification to indicate screenshot saved
+ Context context = mParams.context;
+ Resources r = context.getResources();
+
+ // Create the intent to show the screenshot in gallery
+ Intent launchIntent = new Intent(Intent.ACTION_VIEW);
+ launchIntent.setDataAndType(mParams.imageUri, "image/png");
+ launchIntent.setFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ final long now = System.currentTimeMillis();
+
+ // Update the text and the icon for the existing notification
+ mPublicNotificationBuilder
+ .setContentTitle(r.getString(R.string.screenshot_saved_title))
+ .setContentText(r.getString(R.string.screenshot_saved_text))
+ .setContentIntent(
+ PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
+ .setWhen(now)
+ .setAutoCancel(true)
+ .setColor(context.getColor(
+ com.android.internal.R.color.system_notification_accent_color));
+ mNotificationBuilder
+ .setContentTitle(r.getString(R.string.screenshot_saved_title))
+ .setContentText(r.getString(R.string.screenshot_saved_text))
+ .setContentIntent(PendingIntent.getActivity(mParams.context, 0,
+ launchIntent, 0))
+ .setWhen(now)
+ .setAutoCancel(true)
+ .setColor(context.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setPublicVersion(mPublicNotificationBuilder.build())
+ .setFlag(Notification.FLAG_NO_CLEAR, false);
+
+ mNotificationManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT,
+ mNotificationBuilder.build());
+ }
}
+ mParams.finisher.run();
+ mParams.clearContext();
}
- mParams.finisher.run();
- mParams.clearContext();
- }
- @Override
- protected void onCancelled(Void params) {
- // If we are cancelled while the task is running in the background, we may get null params.
- // The finisher is expected to always be called back, so just use the baked-in params from
- // the ctor in any case.
- mParams.finisher.run();
- mParams.clearImage();
- mParams.clearContext();
-
- // Cancel the posted notification
- mNotificationManager.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
+ @Override
+ protected void onCancelled(Void params) {
+ // If we are cancelled while the task is running in the background, we may get null
+ // params. The finisher is expected to always be called back, so just use the baked-in
+ // params from the ctor in any case.
+ mParams.finisher.run();
+ mParams.clearImage();
+ mParams.clearContext();
+
+ // Cancel the posted notification
+ mNotificationManager.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
+ }
}
-}
-/**
- * An AsyncTask that deletes an image from the media store in the background.
- */
-class DeleteImageInBackgroundTask extends AsyncTask<Uri, Void, Void> {
- private Context mContext;
+ /**
+ * An AsyncTask that deletes an image from the media store in the background.
+ */
+ private static class DeleteImageInBackgroundTask extends AsyncTask<Uri, Void, Void> {
+ private Context mContext;
- DeleteImageInBackgroundTask(Context context) {
- mContext = context;
- }
+ DeleteImageInBackgroundTask(Context context) {
+ mContext = context;
+ }
- @Override
- protected Void doInBackground(Uri... params) {
- if (params.length != 1) return null;
+ @Override
+ protected Void doInBackground(Uri... params) {
+ if (params.length != 1) return null;
- Uri screenshotUri = params[0];
- ContentResolver resolver = mContext.getContentResolver();
- resolver.delete(screenshotUri, null, null);
- return null;
+ Uri screenshotUri = params[0];
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.delete(screenshotUri, null, null);
+ return null;
+ }
}
-}
-@Singleton
-public class GlobalScreenshot {
static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id";
static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent";
static final String EXTRA_CANCEL_NOTIFICATION = "android:screenshot_cancel_notification";
@@ -1032,6 +1094,58 @@ public class GlobalScreenshot {
nManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT, n);
}
+ @VisibleForTesting
+ static CompletableFuture<List<Notification.Action>> getSmartActionsFuture(Context context,
+ Bitmap image, ScreenshotNotificationSmartActionsProvider smartActionsProvider,
+ Handler handler, boolean smartActionsEnabled, boolean isManagedProfile) {
+ if (!smartActionsEnabled) {
+ Slog.i(TAG, "Screenshot Intelligence not enabled, returning empty list.");
+ return CompletableFuture.completedFuture(Collections.emptyList());
+ }
+ if (image.getConfig() != Bitmap.Config.HARDWARE) {
+ Slog.w(TAG, String.format(
+ "Bitmap expected: Hardware, Bitmap found: %s. Returning empty list.",
+ image.getConfig()));
+ return CompletableFuture.completedFuture(Collections.emptyList());
+ }
+
+ Slog.d(TAG, "Screenshot from a managed profile: " + isManagedProfile);
+ CompletableFuture<List<Notification.Action>> smartActionsFuture;
+ try {
+ ActivityManager.RunningTaskInfo runningTask =
+ ActivityManagerWrapper.getInstance().getRunningTask();
+ ComponentName componentName =
+ (runningTask != null && runningTask.topActivity != null)
+ ? runningTask.topActivity
+ : new ComponentName("", "");
+ smartActionsFuture = smartActionsProvider.getActions(image, context,
+ THREAD_POOL_EXECUTOR,
+ handler,
+ componentName,
+ isManagedProfile);
+ } catch (Throwable e) {
+ smartActionsFuture = CompletableFuture.completedFuture(Collections.emptyList());
+ Slog.e(TAG, "Failed to get future for screenshot notification smart actions.", e);
+ }
+ return smartActionsFuture;
+ }
+
+ @VisibleForTesting
+ static List<Notification.Action> getSmartActions(
+ CompletableFuture<List<Notification.Action>> smartActionsFuture, int timeoutMs) {
+ try {
+ long startTimeMs = SystemClock.uptimeMillis();
+ List<Notification.Action> actions = smartActionsFuture.get(timeoutMs,
+ TimeUnit.MILLISECONDS);
+ Slog.d(TAG, String.format("Wait time for smart actions: %d ms",
+ SystemClock.uptimeMillis() - startTimeMs));
+ return actions;
+ } catch (Throwable e) {
+ Slog.e(TAG, "Failed to obtain screenshot notification smart actions.", e);
+ return Collections.emptyList();
+ }
+ }
+
/**
* Receiver to proxy the share or edit intent, used to clean up the notification and send
* appropriate signals to the system (ie. to dismiss the keyguard if necessary).
@@ -1041,8 +1155,9 @@ public class GlobalScreenshot {
private final StatusBar mStatusBar;
@Inject
- public ActionProxyReceiver(StatusBar statusBar) {
- mStatusBar = statusBar;
+ public ActionProxyReceiver(Optional<Lazy<StatusBar>> statusBarLazy) {
+ Lazy<StatusBar> statusBar = statusBarLazy.orElse(null);
+ mStatusBar = statusBar != null ? statusBar.get() : null;
}
@Override
@@ -1067,8 +1182,13 @@ public class GlobalScreenshot {
context.startActivityAsUser(actionIntent, opts.toBundle(), UserHandle.CURRENT);
};
- mStatusBar.executeRunnableDismissingKeyguard(startActivityRunnable, null,
- true /* dismissShade */, true /* afterKeyguardGone */, true /* deferred */);
+ if (mStatusBar != null) {
+ mStatusBar.executeRunnableDismissingKeyguard(startActivityRunnable, null,
+ true /* dismissShade */, true /* afterKeyguardGone */,
+ true /* deferred */);
+ } else {
+ startActivityRunnable.run();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java
new file mode 100644
index 000000000000..fa23bf7d5bde
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java
@@ -0,0 +1,58 @@
+/*
+ * 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.screenshot;
+
+import android.app.Notification;
+import android.content.ComponentName;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.os.Handler;
+import android.util.Log;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+
+/**
+ * This class can be overridden by a vendor-specific sys UI implementation,
+ * in order to provide smart actions in the screenshot notification.
+ */
+public class ScreenshotNotificationSmartActionsProvider {
+ private static final String TAG = "ScreenshotActions";
+
+ /**
+ * Default implementation that returns an empty list.
+ * This method is overridden in vendor-specific Sys UI implementation.
+ *
+ * @param bitmap The bitmap of the screenshot. The bitmap config must be {@link
+ * HARDWARE}.
+ * @param context The current app {@link Context}.
+ * @param executor A {@link Executor} that can be used to execute tasks in parallel.
+ * @param handler A {@link Handler} to possibly run UI-thread code.
+ * @param componentName Contains package and activity class names where the screenshot was
+ * taken. This is used as an additional signal to generate and rank more
+ * relevant actions.
+ * @param isManagedProfile The screenshot was taken for a work profile app.
+ */
+ public CompletableFuture<List<Notification.Action>> getActions(Bitmap bitmap, Context context,
+ Executor executor, Handler handler, ComponentName componentName,
+ boolean isManagedProfile) {
+ Log.d(TAG, "Returning empty smart action list.");
+ return CompletableFuture.completedFuture(Collections.emptyList());
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index df9791d1bd37..a571f011fff3 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -34,13 +34,18 @@ import com.android.systemui.recents.Recents;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.stackdivider.DividerView;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Dispatches shortcut to System UI components
*/
+@Singleton
public class ShortcutKeyDispatcher extends SystemUI
implements ShortcutKeyServiceProxy.Callbacks {
private static final String TAG = "ShortcutKeyDispatcher";
+ private final Divider mDivider;
private ShortcutKeyServiceProxy mShortcutKeyServiceProxy = new ShortcutKeyServiceProxy(this);
private IWindowManager mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
@@ -53,8 +58,10 @@ public class ShortcutKeyDispatcher extends SystemUI
protected final long SC_DOCK_LEFT = META_MASK | KeyEvent.KEYCODE_LEFT_BRACKET;
protected final long SC_DOCK_RIGHT = META_MASK | KeyEvent.KEYCODE_RIGHT_BRACKET;
- public ShortcutKeyDispatcher(Context context) {
+ @Inject
+ public ShortcutKeyDispatcher(Context context, Divider divider) {
super(context);
+ mDivider = divider;
}
/**
@@ -95,7 +102,7 @@ public class ShortcutKeyDispatcher extends SystemUI
: SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT, null, -1);
} else {
// If there is already a docked window, we respond by resizing the docking pane.
- DividerView dividerView = getComponent(Divider.class).getView();
+ DividerView dividerView = mDivider.getView();
DividerSnapAlgorithm snapAlgorithm = dividerView.getSnapAlgorithm();
int dividerPosition = dividerView.getCurrentPosition();
DividerSnapAlgorithm.SnapTarget currentTarget =
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index c8b2b6aee0b3..d12f3ee5a1ec 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -59,7 +59,6 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks {
public void start() {
mWindowManager = new DividerWindowManager(mContext);
update(mContext.getResources().getConfiguration());
- putComponent(Divider.class, this);
mDockDividerVisibilityListener = new DockDividerVisibilityListener();
try {
WindowManagerGlobal.getWindowManagerService().registerDockedStackListener(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index eb6ea13a6690..621f101cd8af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -22,8 +22,6 @@ import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEF
import static android.inputmethodservice.InputMethodService.IME_INVISIBLE;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
-import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.TYPE_TOP_BAR;
import static com.android.systemui.statusbar.phone.StatusBar.ONLY_CORE_APPS;
@@ -34,7 +32,6 @@ import android.app.StatusBarManager.WindowType;
import android.app.StatusBarManager.WindowVisibleState;
import android.content.ComponentName;
import android.content.Context;
-import android.graphics.Rect;
import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.hardware.display.DisplayManager;
import android.inputmethodservice.InputMethodService.BackDispositionMode;
@@ -45,13 +42,9 @@ import android.os.Looper;
import android.os.Message;
import android.util.Pair;
import android.util.SparseArray;
-import android.view.InsetsFlags;
import android.view.InsetsState.InternalInsetType;
-import android.view.View;
import android.view.WindowInsetsController.Appearance;
-import androidx.annotation.VisibleForTesting;
-
import com.android.internal.os.SomeArgs;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.StatusBarIcon;
@@ -61,9 +54,6 @@ import com.android.systemui.statusbar.policy.CallbackController;
import java.util.ArrayList;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
/**
* This class takes the functions from IStatusBar that come in on
* binder pool threads and posts messages to get them onto the main
@@ -71,7 +61,6 @@ import javax.inject.Singleton;
* coalescing these calls so they don't stack up. For the calls
* are coalesced, note that they are all idempotent.
*/
-@Singleton
public class CommandQueue extends IStatusBar.Stub implements CallbackController<Callbacks>,
DisplayManager.DisplayListener {
private static final int INDEX_MASK = 0xffff;
@@ -307,8 +296,6 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
}
}
- @VisibleForTesting
- @Inject
public CommandQueue(Context context) {
context.getSystemService(DisplayManager.class).registerDisplayListener(this, mHandler);
// We always have default display.
@@ -470,42 +457,6 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
}
}
- // TODO(b/118118435): Remove this function after migration
- @Override
- public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
- boolean navbarColorManagedByIme) {
- synchronized (mLock) {
- final boolean hasDockedStack = !dockedStackBounds.isEmpty();
- final boolean transientStatus = (vis & View.STATUS_BAR_TRANSIENT) != 0;
- final boolean transientNavigation = (vis & View.NAVIGATION_BAR_TRANSIENT) != 0;
- if (transientStatus && transientNavigation) {
- showTransient(displayId, new int[]{TYPE_TOP_BAR, TYPE_NAVIGATION_BAR});
- } else if (transientStatus) {
- showTransient(displayId, new int[]{TYPE_TOP_BAR});
- abortTransient(displayId, new int[]{TYPE_NAVIGATION_BAR});
- } else if (transientNavigation) {
- showTransient(displayId, new int[]{TYPE_NAVIGATION_BAR});
- abortTransient(displayId, new int[]{TYPE_TOP_BAR});
- } else {
- abortTransient(displayId, new int[]{TYPE_TOP_BAR, TYPE_NAVIGATION_BAR});
- }
- SomeArgs args = SomeArgs.obtain();
- args.argi1 = displayId;
- args.argi2 = InsetsFlags.getAppearance(vis);
- args.argi3 = navbarColorManagedByIme ? 1 : 0;
- final int fullscreenAppearance = InsetsFlags.getAppearance(fullscreenStackVis);
- final int dockedAppearance = InsetsFlags.getAppearance(dockedStackVis);
- args.arg1 = hasDockedStack
- ? new AppearanceRegion[]{
- new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds),
- new AppearanceRegion(dockedAppearance, dockedStackBounds)}
- : new AppearanceRegion[]{
- new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds)};
- mHandler.obtainMessage(MSG_SYSTEM_BAR_APPEARANCE_CHANGED, args).sendToTarget();
- }
- }
-
@Override
public void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
synchronized (mLock) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 681f3abaea91..2ef1f40f2f58 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -107,6 +107,7 @@ public class KeyguardIndicationController implements StateListener,
private ColorStateList mTransientTextColorState;
private ColorStateList mInitialTextColorState;
private boolean mVisible;
+ private boolean mHideTransientMessageOnScreenOff;
private boolean mPowerPluggedIn;
private boolean mPowerPluggedInWired;
@@ -295,15 +296,17 @@ public class KeyguardIndicationController implements StateListener,
* Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
*/
public void showTransientIndication(CharSequence transientIndication) {
- showTransientIndication(transientIndication, mInitialTextColorState);
+ showTransientIndication(transientIndication, mInitialTextColorState,
+ false /* hideOnScreenOff */);
}
/**
* Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
*/
- public void showTransientIndication(CharSequence transientIndication,
- ColorStateList textColorState) {
+ private void showTransientIndication(CharSequence transientIndication,
+ ColorStateList textColorState, boolean hideOnScreenOff) {
mTransientIndication = transientIndication;
+ mHideTransientMessageOnScreenOff = hideOnScreenOff && transientIndication != null;
mTransientTextColorState = textColorState;
mHandler.removeMessages(MSG_HIDE_TRANSIENT);
mHandler.removeMessages(MSG_SWIPE_UP_TO_UNLOCK);
@@ -322,6 +325,7 @@ public class KeyguardIndicationController implements StateListener,
public void hideTransientIndication() {
if (mTransientIndication != null) {
mTransientIndication = null;
+ mHideTransientMessageOnScreenOff = false;
mHandler.removeMessages(MSG_HIDE_TRANSIENT);
updateIndication(false);
}
@@ -544,7 +548,8 @@ public class KeyguardIndicationController implements StateListener,
String message = mContext.getString(R.string.keyguard_retry);
mStatusBarKeyguardViewManager.showBouncerMessage(message, mInitialTextColorState);
} else if (mKeyguardUpdateMonitor.isScreenOn()) {
- showTransientIndication(mContext.getString(R.string.keyguard_unlock));
+ showTransientIndication(mContext.getString(R.string.keyguard_unlock),
+ mInitialTextColorState, true /* hideOnScreenOff */);
hideTransientIndicationDelayed(BaseKeyguardCallback.HIDE_DELAY_MS);
}
}
@@ -554,7 +559,11 @@ public class KeyguardIndicationController implements StateListener,
return;
}
mDozing = dozing;
- updateIndication(false);
+ if (mHideTransientMessageOnScreenOff && mDozing) {
+ hideTransientIndication();
+ } else {
+ updateIndication(false);
+ }
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -616,8 +625,7 @@ public class KeyguardIndicationController implements StateListener,
@Override
public void onBiometricHelp(int msgId, String helpString,
BiometricSourceType biometricSourceType) {
- KeyguardUpdateMonitor updateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
- if (!updateMonitor.isUnlockingWithBiometricAllowed()) {
+ if (!mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed()) {
return;
}
boolean showSwipeToUnlock =
@@ -625,8 +633,8 @@ public class KeyguardIndicationController implements StateListener,
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
mStatusBarKeyguardViewManager.showBouncerMessage(helpString,
mInitialTextColorState);
- } else if (updateMonitor.isScreenOn()) {
- showTransientIndication(helpString);
+ } else if (mKeyguardUpdateMonitor.isScreenOn()) {
+ showTransientIndication(helpString, mInitialTextColorState, showSwipeToUnlock);
if (!showSwipeToUnlock) {
hideTransientIndicationDelayed(TRANSIENT_BIOMETRIC_ERROR_TIMEOUT);
}
@@ -640,8 +648,7 @@ public class KeyguardIndicationController implements StateListener,
@Override
public void onBiometricError(int msgId, String errString,
BiometricSourceType biometricSourceType) {
- KeyguardUpdateMonitor updateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
- if (shouldSuppressBiometricError(msgId, biometricSourceType, updateMonitor)) {
+ if (shouldSuppressBiometricError(msgId, biometricSourceType, mKeyguardUpdateMonitor)) {
return;
}
animatePadlockError();
@@ -651,7 +658,7 @@ public class KeyguardIndicationController implements StateListener,
showSwipeUpToUnlock();
} else if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
mStatusBarKeyguardViewManager.showBouncerMessage(errString, mInitialTextColorState);
- } else if (updateMonitor.isScreenOn()) {
+ } else if (mKeyguardUpdateMonitor.isScreenOn()) {
showTransientIndication(errString);
// We want to keep this message around in case the screen was off
hideTransientIndicationDelayed(HIDE_DELAY_MS);
@@ -691,13 +698,15 @@ public class KeyguardIndicationController implements StateListener,
@Override
public void onTrustAgentErrorMessage(CharSequence message) {
- showTransientIndication(message, Utils.getColorError(mContext));
+ showTransientIndication(message, Utils.getColorError(mContext),
+ false /* hideOnScreenOff */);
}
@Override
public void onScreenTurnedOn() {
if (mMessageToShowOnScreenOn != null) {
- showTransientIndication(mMessageToShowOnScreenOn, Utils.getColorError(mContext));
+ showTransientIndication(mMessageToShowOnScreenOn, Utils.getColorError(mContext),
+ false /* hideOnScreenOff */);
// We want to keep this message around in case the screen was off
hideTransientIndicationDelayed(HIDE_DELAY_MS);
mMessageToShowOnScreenOn = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java
new file mode 100644
index 000000000000..d1f6ebf3826d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java
@@ -0,0 +1,40 @@
+/*
+ * 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;
+
+import android.content.Context;
+
+import javax.inject.Singleton;
+
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger Module providing common dependencies of StatusBar.
+ */
+@Module
+public class StatusBarDependenciesModule {
+ /**
+ * Provides our instance of CommandQueue which is considered optional.
+ */
+ @Provides
+ @Singleton
+ public CommandQueue provideCommandQueue(Context context) {
+ return new CommandQueue(context);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java
new file mode 100644
index 000000000000..bc7c22d65a44
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.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.systemui.statusbar;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.StatusBarWindowView;
+import com.android.systemui.util.InjectionInflationController;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Creates a single instance of super_status_bar that can be shared across various system ui
+ * objects.
+ */
+@Singleton
+public class SuperStatusBarViewFactory {
+
+ private final Context mContext;
+ private final InjectionInflationController mInjectionInflationController;
+
+ private StatusBarWindowView mStatusBarWindowView;
+ private NotificationShelf mNotificationShelf;
+
+ @Inject
+ public SuperStatusBarViewFactory(Context context,
+ InjectionInflationController injectionInflationController) {
+ mContext = context;
+ mInjectionInflationController = injectionInflationController;
+ }
+
+ /**
+ * Gets the inflated {@link StatusBarWindowView} from {@link R.layout#super_status_bar}. Returns
+ * a cached instance, if it has already been inflated.
+ */
+ public StatusBarWindowView getStatusBarWindowView() {
+ if (mStatusBarWindowView != null) {
+ return mStatusBarWindowView;
+ }
+
+ mStatusBarWindowView = (StatusBarWindowView) mInjectionInflationController.injectable(
+ LayoutInflater.from(mContext)).inflate(R.layout.super_status_bar,
+ /* root= */ null);
+ if (mStatusBarWindowView == null) {
+ throw new IllegalStateException(
+ "R.layout.super_status_bar could not be properly inflated");
+ }
+ return mStatusBarWindowView;
+ }
+
+ /**
+ * Gets the inflated {@link NotificationShelf} from
+ * {@link R.layout#status_bar_notification_shelf}.
+ * Returns a cached instance, if it has already been inflated.
+ *
+ * @param container the expected container to hold the {@link NotificationShelf}. The view
+ * isn't immediately attached, but the layout params of this view is used
+ * during inflation.
+ */
+ public NotificationShelf getNotificationShelf(ViewGroup container) {
+ if (mNotificationShelf != null) {
+ return mNotificationShelf;
+ }
+
+ mNotificationShelf = (NotificationShelf) mInjectionInflationController.injectable(
+ LayoutInflater.from(mContext)).inflate(R.layout.status_bar_notification_shelf,
+ container, /* attachToRoot= */ false);
+ if (mNotificationShelf == null) {
+ throw new IllegalStateException(
+ "R.layout.status_bar_notification_shelf could not be properly inflated");
+ }
+ return mNotificationShelf;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
index 396c5fefd8b7..0ef75165f54f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
@@ -142,6 +142,7 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
entry.updateIcons(mContext, sbn);
entry.reset();
updateNotification(entry, pmUser, sbn, entry.getRow());
+ entry.getRow().setOnDismissRunnable(onDismissRunnable);
} else {
entry.createIcons(mContext, sbn);
new RowInflaterTask().inflate(mContext, parent, entry,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index a817f54e77ca..50a20374fee5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -159,6 +159,8 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private int mHeadsUpAddStartLocation;
private float mHeadsUpLocation;
private boolean mIsAppearing;
+ private boolean mDismissed;
+ private boolean mRefocusOnDismiss;
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -1048,6 +1050,27 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
return getHeight();
}
+ /** Mark that this view has been dismissed. */
+ public void dismiss(boolean refocusOnDismiss) {
+ mDismissed = true;
+ mRefocusOnDismiss = refocusOnDismiss;
+ }
+
+ /** Mark that this view is no longer dismissed. */
+ public void unDismiss() {
+ mDismissed = false;
+ }
+
+ /** Is this view marked as dismissed? */
+ public boolean isDismissed() {
+ return mDismissed;
+ }
+
+ /** Should a re-focus occur upon dismissing this view? */
+ public boolean shouldRefocusOnDismiss() {
+ return mRefocusOnDismiss || isAccessibilityFocused();
+ }
+
public interface OnActivatedListener {
void onActivated(ActivatableNotificationView view);
void onActivationReset(ActivatableNotificationView view);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 536db67a8795..f0d07a7ed0bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -95,6 +95,7 @@ import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.SwipeableView;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -114,7 +115,7 @@ import java.util.function.Consumer;
* the group summary (which contains 1 or more child notifications).
*/
public class ExpandableNotificationRow extends ActivatableNotificationView
- implements PluginListener<NotificationMenuRowPlugin> {
+ implements PluginListener<NotificationMenuRowPlugin>, SwipeableView {
private static final boolean DEBUG = false;
private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
@@ -288,7 +289,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
};
private boolean mForceUnlocked;
- private boolean mDismissed;
private boolean mKeepInParent;
private boolean mRemoved;
private static final Property<ExpandableNotificationRow, Float> TRANSLATE_CONTENT =
@@ -307,7 +307,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private boolean mHeadsupDisappearRunning;
private View mChildAfterViewWhenDismissed;
private View mGroupParentWhenDismissed;
- private boolean mRefocusOnDismiss;
private float mContentTransformationAmount;
private boolean mIconsVisible = true;
private boolean mAboveShelf;
@@ -1164,6 +1163,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
}
+ @Override
+ public boolean hasFinishedInitialization() {
+ return getEntry().hasFinishedInitialization();
+ }
+
/**
* Get a handle to a NotificationMenuRowPlugin whose menu view has been added to our hierarchy,
* or null if there is no menu row
@@ -1323,11 +1327,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
}
- public void setDismissed(boolean fromAccessibility) {
+ @Override
+ public void dismiss(boolean refocusOnDismiss) {
+ super.dismiss(refocusOnDismiss);
setLongPressListener(null);
- mDismissed = true;
mGroupParentWhenDismissed = mNotificationParent;
- mRefocusOnDismiss = fromAccessibility;
mChildAfterViewWhenDismissed = null;
mEntry.icon.setDismissed();
if (isChildInGroup()) {
@@ -1340,10 +1344,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
}
- public boolean isDismissed() {
- return mDismissed;
- }
-
public boolean keepInParent() {
return mKeepInParent;
}
@@ -1445,7 +1445,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
groupSummary.getRow().performDismiss(fromAccessibility);
}
}
- setDismissed(fromAccessibility);
+ dismiss(fromAccessibility);
if (mEntry.isClearable()) {
// TODO: beverlyt, log dismissal
// TODO: track dismiss sentiment
@@ -3021,10 +3021,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
return false;
}
- public boolean shouldRefocusOnDismiss() {
- return mRefocusOnDismiss || isAccessibilityFocused();
- }
-
public interface OnExpandClickListener {
void onExpandClicked(NotificationEntry clickedEntry, boolean nowExpanded);
}
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 54d406615ae0..fdd51e9e7790 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
@@ -23,7 +23,6 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.PendingIntent;
import android.content.Intent;
import android.provider.Settings;
import android.view.LayoutInflater;
@@ -310,6 +309,8 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
mParent.removeView(mPeopleHubView);
}
} else {
+ mPeopleHubView.unDismiss();
+ mPeopleHubView.resetTranslation();
if (!currentlyVisible) {
if (mPeopleHubView.getTransientContainer() != null) {
mPeopleHubView.getTransientContainer().removeTransientView(mPeopleHubView);
@@ -419,8 +420,9 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section
}
}
- private void handlePeopleHubClick(PendingIntent pendingIntent) {
- mActivityStarter.startPendingIntentDismissingKeyguard(pendingIntent, null, mPeopleHubView);
+ void hidePeopleRow() {
+ mPeopleHubVisible = false;
+ updateSectionBoundaries();
}
/**
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 6dca7ee9e872..2b9912ce055d 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
@@ -4920,7 +4920,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
} else {
child.setMinClipTopAmount(0);
}
- previousChildWillBeDismissed = StackScrollAlgorithm.canChildBeDismissed(child);
+ previousChildWillBeDismissed = canChildBeDismissed(child);
}
}
@@ -5523,7 +5523,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
performDismissAllAnimations(viewsToHide, closeShade, () -> {
for (ExpandableNotificationRow rowToRemove : viewsToRemove) {
- if (StackScrollAlgorithm.canChildBeDismissed(rowToRemove)) {
+ if (canChildBeDismissed(rowToRemove)) {
if (selection == ROWS_ALL) {
// TODO: This is a listener method; we shouldn't be calling it. Can we just
// call performRemoveNotification as below?
@@ -5552,7 +5552,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
private boolean includeChildInDismissAll(
ExpandableNotificationRow row,
@SelectedRows int selection) {
- return StackScrollAlgorithm.canChildBeDismissed(row) && matchesSelection(row, selection);
+ return canChildBeDismissed(row) && matchesSelection(row, selection);
}
/**
@@ -6223,7 +6223,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
*/
@Override
public void onChildDismissed(View view) {
- ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+ if (!(view instanceof ActivatableNotificationView)) {
+ return;
+ }
+ ActivatableNotificationView row = (ActivatableNotificationView) view;
if (!row.isDismissed()) {
handleChildViewDismissed(view);
}
@@ -6261,6 +6264,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
row.performDismissWithBlockingHelper(false /* fromAccessibility */);
}
+ if (view instanceof PeopleHubView) {
+ PeopleHubView row = (PeopleHubView) view;
+ row.dismiss(false);
+ mSectionsManager.hidePeopleRow();
+ }
+
if (!isBlockingHelperShown) {
mSwipedOutViews.add(view);
}
@@ -6349,9 +6358,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
return 0;
}
- @Override
+ @Override
public boolean canChildBeDismissed(View v) {
- return StackScrollAlgorithm.canChildBeDismissed(v);
+ return NotificationStackScrollLayout.canChildBeDismissed(v);
}
@Override
@@ -6361,6 +6370,23 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
};
+ private static boolean canChildBeDismissed(View v) {
+ if (v instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+ if (row.isBlockingHelperShowingAndTranslationFinished()) {
+ return true;
+ }
+ if (row.areGutsExposed() || !row.getEntry().hasFinishedInitialization()) {
+ return false;
+ }
+ return row.canViewBeDismissed();
+ }
+ if (v instanceof PeopleHubView) {
+ return true;
+ }
+ return false;
+ }
+
// ---------------------- DragDownHelper.OnDragDownListener ------------------------------------
@ShadeViewRefactor(RefactorComponent.INPUT)
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 0968674d31cc..6d0fcc386281 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
@@ -31,11 +31,10 @@ import com.android.systemui.SwipeHelper;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
-class NotificationSwipeHelper extends SwipeHelper
- implements NotificationSwipeActionHelper {
+class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeActionHelper {
+
@VisibleForTesting
protected static final long COVER_MENU_DELAY = 4000;
private static final String TAG = "NotificationSwipeHelper";
@@ -58,12 +57,7 @@ class NotificationSwipeHelper extends SwipeHelper
super(swipeDirection, callback, context, falsingManager);
mMenuListener = menuListener;
mCallback = callback;
- mFalsingCheck = new Runnable() {
- @Override
- public void run() {
- resetExposedMenuView(true /* animate */, true /* force */);
- }
- };
+ mFalsingCheck = () -> resetExposedMenuView(true /* animate */, true /* force */);
}
public View getTranslatingParentView() {
@@ -126,14 +120,14 @@ class NotificationSwipeHelper extends SwipeHelper
// Slide back any notifications that might be showing a menu
resetExposedMenuView(true /* animate */, false /* force */);
- if (currView instanceof ExpandableNotificationRow) {
- initializeRow((ExpandableNotificationRow) currView);
+ if (currView instanceof SwipeableView) {
+ initializeRow((SwipeableView) currView);
}
}
@VisibleForTesting
- protected void initializeRow(ExpandableNotificationRow row) {
- if (row.getEntry().hasFinishedInitialization()) {
+ protected void initializeRow(SwipeableView row) {
+ if (row.hasFinishedInitialization()) {
mCurrMenuRow = row.createMenu();
if (mCurrMenuRow != null) {
mCurrMenuRow.setMenuClickListener(mMenuListener);
@@ -304,8 +298,8 @@ class NotificationSwipeHelper extends SwipeHelper
@Override
public Animator getViewTranslationAnimator(View v, float target,
ValueAnimator.AnimatorUpdateListener listener) {
- if (v instanceof ExpandableNotificationRow) {
- return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener);
+ if (v instanceof SwipeableView) {
+ return ((SwipeableView) v).getTranslateViewAnimator(target, listener);
} else {
return superGetViewTranslationAnimator(v, target, listener);
}
@@ -313,15 +307,15 @@ class NotificationSwipeHelper extends SwipeHelper
@Override
public void setTranslation(View v, float translate) {
- if (v instanceof ExpandableNotificationRow) {
- ((ExpandableNotificationRow) v).setTranslation(translate);
+ if (v instanceof SwipeableView) {
+ ((SwipeableView) v).setTranslation(translate);
}
}
@Override
public float getTranslation(View v) {
- if (v instanceof ExpandableNotificationRow) {
- return ((ExpandableNotificationRow) v).getTranslation();
+ if (v instanceof SwipeableView) {
+ return ((SwipeableView) v).getTranslation();
}
else {
return 0f;
@@ -410,8 +404,8 @@ class NotificationSwipeHelper extends SwipeHelper
if (anim != null) {
anim.start();
}
- } else if (prevMenuExposedView instanceof ExpandableNotificationRow) {
- ExpandableNotificationRow row = (ExpandableNotificationRow) prevMenuExposedView;
+ } else if (prevMenuExposedView instanceof SwipeableView) {
+ SwipeableView row = (SwipeableView) prevMenuExposedView;
if (!row.isRemoved()) {
row.resetTranslation();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
index e31ee024fa36..a0796060e9d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
@@ -16,23 +16,39 @@
package com.android.systemui.statusbar.notification.stack
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.ObjectAnimator
+import android.animation.ValueAnimator
import android.content.Context
import android.util.AttributeSet
+import android.util.FloatProperty
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.android.systemui.R
-import com.android.systemui.statusbar.notification.people.PersonViewModel
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin
import com.android.systemui.statusbar.notification.people.DataListener
+import com.android.systemui.statusbar.notification.people.PersonViewModel
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView
+private val TRANSLATE_CONTENT = object : FloatProperty<PeopleHubView>("translate") {
+ override fun setValue(view: PeopleHubView, value: Float) {
+ view.translation = value
+ }
+
+ override fun get(view: PeopleHubView) = view.translation
+}
+
class PeopleHubView(context: Context, attrs: AttributeSet) :
- ActivatableNotificationView(context, attrs) {
+ ActivatableNotificationView(context, attrs), SwipeableView {
private lateinit var contents: ViewGroup
private lateinit var personControllers: List<PersonDataListenerImpl>
+ private var translateAnim: ObjectAnimator? = null
+
val personViewAdapters: Sequence<DataListener<PersonViewModel?>>
get() = personControllers.asSequence()
@@ -49,6 +65,34 @@ class PeopleHubView(context: Context, attrs: AttributeSet) :
override fun getContentView(): View = contents
+ override fun hasFinishedInitialization(): Boolean = true
+
+ override fun createMenu(): NotificationMenuRowPlugin? = null
+
+ override fun getTranslateViewAnimator(
+ leftTarget: Float,
+ listener: ValueAnimator.AnimatorUpdateListener?
+ ): Animator =
+ ObjectAnimator
+ .ofFloat(this, TRANSLATE_CONTENT, leftTarget)
+ .apply {
+ listener?.let { addUpdateListener(listener) }
+ addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(anim: Animator) {
+ translateAnim = null
+ }
+ })
+ }
+ .also {
+ translateAnim?.cancel()
+ translateAnim = it
+ }
+
+ override fun resetTranslation() {
+ translateAnim?.cancel()
+ translationX = 0f
+ }
+
private inner class PersonDataListenerImpl(val viewGroup: ViewGroup) :
DataListener<PersonViewModel?> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 4b61064f4a54..9646c01c8c41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -195,20 +195,6 @@ public class StackScrollAlgorithm {
}
}
- public static boolean canChildBeDismissed(View v) {
- if (!(v instanceof ExpandableNotificationRow)) {
- return false;
- }
- ExpandableNotificationRow row = (ExpandableNotificationRow) v;
- if (row.isBlockingHelperShowingAndTranslationFinished()) {
- return true;
- }
- if (row.areGutsExposed() || !row.getEntry().hasFinishedInitialization()) {
- return false;
- }
- return row.canViewBeDismissed();
- }
-
/**
* Updates the dimmed, activated and hiding sensitive states of the children.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SwipeableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SwipeableView.java
new file mode 100644
index 000000000000..6c6ef61cfdaf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SwipeableView.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.stack;
+
+import android.animation.Animator;
+import android.animation.ValueAnimator;
+
+import androidx.annotation.Nullable;
+
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+
+/** A View that is swipeable inside of the notification shade. */
+public interface SwipeableView {
+
+ /** Has this view finished initializing? */
+ boolean hasFinishedInitialization();
+
+ /** Optionally creates a menu for this view. */
+ @Nullable NotificationMenuRowPlugin createMenu();
+
+ /** Animator for translating the view, simulating a swipe. */
+ Animator getTranslateViewAnimator(
+ float leftTarget, ValueAnimator.AnimatorUpdateListener listener);
+
+ /** Sets the translation amount for an in-progress swipe. */
+ void setTranslation(float translate);
+
+ /** Gets the current translation amount. */
+ float getTranslation();
+
+ /** Has this view been removed? */
+ boolean isRemoved();
+
+ /** Resets the swipe translation back to zero state. */
+ void resetTranslation();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index fce1dcc998fe..c2731089132c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -203,10 +203,16 @@ public class ButtonDispatcher {
mFadeAnimator.addUpdateListener(mAlphaListener);
mFadeAnimator.start();
} else {
- mAlpha = alpha;
- final int N = mViews.size();
- for (int i = 0; i < N; i++) {
- mViews.get(i).setAlpha(alpha);
+ // Discretize the alpha updates to prevent too frequent updates when there is a long
+ // alpha animation
+ int prevAlpha = (int) (getAlpha() * 255);
+ int nextAlpha = (int) (alpha * 255);
+ if (prevAlpha != nextAlpha) {
+ mAlpha = nextAlpha / 255f;
+ final int N = mViews.size();
+ for (int i = 0; i < N; i++) {
+ mViews.get(i).setAlpha(mAlpha);
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 2e776e39b54c..1532c4f977e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -247,7 +247,7 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("LightBarController: ");
- pw.print(" mAppearance=0x"); pw.println(ViewDebug.flagsToString(
+ pw.print(" mAppearance="); pw.println(ViewDebug.flagsToString(
InsetsFlags.class, "appearance", mAppearance));
final int numStacks = mAppearanceRegions.length;
for (int i = 0; i < numStacks; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java
new file mode 100644
index 000000000000..93887a6617f9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.annotation.Nullable;
+import android.view.View;
+import android.view.WindowInsetsController;
+import android.view.WindowManager;
+import android.view.animation.AccelerateInterpolator;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.internal.view.AppearanceRegion;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.notification.NotificationEntryListener;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Apps can request a low profile mode {@link View.SYSTEM_UI_FLAG_LOW_PROFILE}
+ * where status bar and navigation icons dim. In this mode, a notification dot appears
+ * where the notification icons would appear if they would be shown outside of this mode.
+ *
+ * This controller shows and hides the notification dot in the status bar to indicate
+ * whether there are notifications when the device is in {@link View.SYSTEM_UI_FLAG_LOW_PROFILE}.
+ */
+@Singleton
+public class LightsOutNotifController {
+ private final CommandQueue mCommandQueue;
+ private final NotificationEntryManager mEntryManager;
+ private final WindowManager mWindowManager;
+
+ /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int) */
+ @VisibleForTesting @WindowInsetsController.Appearance int mAppearance;
+
+ private int mDisplayId;
+ private View mLightsOutNotifView;
+
+ @Inject
+ LightsOutNotifController(WindowManager windowManager,
+ NotificationEntryManager entryManager,
+ CommandQueue commandQueue) {
+ mWindowManager = windowManager;
+ mEntryManager = entryManager;
+ mCommandQueue = commandQueue;
+ }
+
+ /**
+ * Sets the notification dot view after it is created in the StatusBar.
+ * This is the view this controller will show and hide depending on whether:
+ * 1. there are active notifications
+ * 2. an app has requested {@link View.SYSTEM_UI_FLAG_LOW_PROFILE}
+ */
+ void setLightsOutNotifView(View lightsOutNotifView) {
+ destroy();
+ mLightsOutNotifView = lightsOutNotifView;
+
+ if (mLightsOutNotifView != null) {
+ mLightsOutNotifView.setVisibility(View.GONE);
+ mLightsOutNotifView.setAlpha(0f);
+ init();
+ }
+ }
+
+ private void destroy() {
+ mEntryManager.removeNotificationEntryListener(mEntryListener);
+ mCommandQueue.removeCallback(mCallback);
+ }
+
+ private void init() {
+ mDisplayId = mWindowManager.getDefaultDisplay().getDisplayId();
+ mEntryManager.addNotificationEntryListener(mEntryListener);
+ mCommandQueue.addCallback(mCallback);
+
+ updateLightsOutView();
+ }
+
+ private boolean hasActiveNotifications() {
+ return !mEntryManager.getNotificationData().getActiveNotifications().isEmpty();
+ }
+
+ @VisibleForTesting
+ void updateLightsOutView() {
+ if (mLightsOutNotifView == null) {
+ return;
+ }
+
+ final boolean showDot = shouldShowDot();
+ if (showDot != isShowingDot()) {
+ if (showDot) {
+ mLightsOutNotifView.setAlpha(0f);
+ mLightsOutNotifView.setVisibility(View.VISIBLE);
+ }
+
+ mLightsOutNotifView.animate()
+ .alpha(showDot ? 1 : 0)
+ .setDuration(showDot ? 750 : 250)
+ .setInterpolator(new AccelerateInterpolator(2.0f))
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator a) {
+ mLightsOutNotifView.setAlpha(showDot ? 1 : 0);
+ mLightsOutNotifView.setVisibility(showDot ? View.VISIBLE : View.GONE);
+ }
+ })
+ .start();
+ }
+ }
+
+ @VisibleForTesting
+ boolean isShowingDot() {
+ return mLightsOutNotifView.getVisibility() == View.VISIBLE
+ && mLightsOutNotifView.getAlpha() == 1.0f;
+ }
+
+ @VisibleForTesting
+ boolean shouldShowDot() {
+ return hasActiveNotifications() && areLightsOut();
+ }
+
+ @VisibleForTesting
+ boolean areLightsOut() {
+ return 0 != (mAppearance & APPEARANCE_LOW_PROFILE_BARS);
+ }
+
+ private final CommandQueue.Callbacks mCallback = new CommandQueue.Callbacks() {
+ @Override
+ public void onSystemBarAppearanceChanged(int displayId,
+ @WindowInsetsController.Appearance int appearance,
+ AppearanceRegion[] appearanceRegions,
+ boolean navbarColorManagedByIme) {
+ if (displayId != mDisplayId) {
+ return;
+ }
+ mAppearance = appearance;
+ updateLightsOutView();
+ }
+ };
+
+ private final NotificationEntryListener mEntryListener = new NotificationEntryListener() {
+ // Cares about notifications post-filtering
+ @Override
+ public void onNotificationAdded(NotificationEntry entry) {
+ updateLightsOutView();
+ }
+
+ @Override
+ public void onPostEntryUpdated(NotificationEntry entry) {
+ updateLightsOutView();
+ }
+
+ @Override
+ public void onEntryRemoved(@Nullable NotificationEntry entry,
+ NotificationVisibility visibility, boolean removedByUser) {
+ updateLightsOutView();
+ }
+ };
+}
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 816327fe19bd..1c46cf8762db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -118,6 +118,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.List;
import java.util.Locale;
+import java.util.Optional;
import java.util.function.Consumer;
import javax.inject.Inject;
@@ -162,8 +163,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
private int mDisabledFlags1;
private int mDisabledFlags2;
private StatusBar mStatusBar;
- private Recents mRecents;
- private Divider mDivider;
+ private final Divider mDivider;
+ private final Optional<Recents> mRecentsOptional;
private WindowManager mWindowManager;
private final CommandQueue mCommandQueue;
private long mLastLockToAppLongPress;
@@ -266,7 +267,9 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
StatusBarStateController statusBarStateController,
SysUiState sysUiFlagsContainer,
BroadcastDispatcher broadcastDispatcher,
- CommandQueue commandQueue) {
+ CommandQueue commandQueue,
+ Divider divider,
+ Optional<Recents> recentsOptional) {
mAccessibilityManagerWrapper = accessibilityManagerWrapper;
mDeviceProvisionedController = deviceProvisionedController;
mStatusBarStateController = statusBarStateController;
@@ -279,6 +282,8 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
mNavBarMode = navigationModeController.addListener(this);
mBroadcastDispatcher = broadcastDispatcher;
mCommandQueue = commandQueue;
+ mDivider = divider;
+ mRecentsOptional = recentsOptional;
}
// ----- Fragment Lifecycle Callbacks -----
@@ -288,8 +293,6 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
super.onCreate(savedInstanceState);
mCommandQueue.observe(getLifecycle(), this);
mStatusBar = SysUiServiceProvider.getComponent(getContext(), StatusBar.class);
- mRecents = SysUiServiceProvider.getComponent(getContext(), Recents.class);
- mDivider = SysUiServiceProvider.getComponent(getContext(), Divider.class);
mWindowManager = getContext().getSystemService(WindowManager.class);
mAccessibilityManager = getContext().getSystemService(AccessibilityManager.class);
mContentResolver = getContext().getContentResolver();
@@ -905,7 +908,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
}
private boolean onLongPressRecents() {
- if (mRecents == null || !ActivityTaskManager.supportsMultiWindow(getContext())
+ if (mRecentsOptional.isPresent() || !ActivityTaskManager.supportsMultiWindow(getContext())
|| !mDivider.getView().getSnapAlgorithm().isSplitScreenFeasible()
|| ActivityManager.isLowRamDeviceStatic()
// If we are connected to the overview service, then disable the recents button
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
index 4f7af58094ec..abceb11b36e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
@@ -31,13 +31,13 @@ import com.android.settingslib.Utils;
import com.android.systemui.R;
public class NavigationHandle extends View implements ButtonInterface {
- private float mDarkIntensity = -1;
private final Paint mPaint = new Paint();
private @ColorInt final int mLightColor;
private @ColorInt final int mDarkColor;
private final int mRadius;
private final int mBottom;
+ private boolean mRequiresInvalidate;
public NavigationHandle(Context context) {
this(context, null);
@@ -60,6 +60,15 @@ public class NavigationHandle extends View implements ButtonInterface {
}
@Override
+ public void setAlpha(float alpha) {
+ super.setAlpha(alpha);
+ if (alpha > 0f && mRequiresInvalidate) {
+ mRequiresInvalidate = false;
+ invalidate();
+ }
+ }
+
+ @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
@@ -85,11 +94,15 @@ public class NavigationHandle extends View implements ButtonInterface {
@Override
public void setDarkIntensity(float intensity) {
- if (mDarkIntensity != intensity) {
- mPaint.setColor((int) ArgbEvaluator.getInstance().evaluate(intensity, mLightColor,
- mDarkColor));
- mDarkIntensity = intensity;
- invalidate();
+ int color = (int) ArgbEvaluator.getInstance().evaluate(intensity, mLightColor, mDarkColor);
+ if (mPaint.getColor() != color) {
+ mPaint.setColor(color);
+ if (getVisibility() == VISIBLE && getAlpha() > 0) {
+ invalidate();
+ } else {
+ // If we are currently invisible, then invalidate when we are next made visible
+ mRequiresInvalidate = true;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
index 70cd43a5e17a..f359fe7cfec4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ShadeController.java
@@ -142,12 +142,6 @@ public interface ShadeController {
void onLaunchAnimationCancelled();
/**
- * When notifications update, give the shade controller a chance to do thing in response to
- * the new data set
- */
- void updateAreThereNotifications();
-
- /**
* Callback to notify the shade controller that a {@link ActivatableNotificationView} has become
* inactive
*/
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 4148a73e579c..6be881669146 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -24,7 +24,6 @@ import static android.app.StatusBarManager.WindowType;
import static android.app.StatusBarManager.WindowVisibleState;
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
-import static android.view.InsetsFlags.getAppearance;
import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.InsetsState.containsType;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
@@ -48,8 +47,6 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARE
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING;
import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -75,7 +72,6 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PointF;
import android.media.AudioAttributes;
@@ -109,7 +105,6 @@ import android.view.Display;
import android.view.IWindowManager;
import android.view.InsetsState.InternalInsetType;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.RemoteAnimationAdapter;
import android.view.ThreadedRenderer;
@@ -120,7 +115,6 @@ import android.view.WindowInsetsController.Appearance;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityManager;
-import android.view.animation.AccelerateInterpolator;
import android.widget.DateTimeView;
import com.android.internal.annotations.VisibleForTesting;
@@ -157,7 +151,6 @@ import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.charging.WirelessChargingAnimation;
import com.android.systemui.classifier.FalsingLog;
import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.dagger.SystemUIBinder;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.fragments.ExtensionFragmentListener;
@@ -202,6 +195,7 @@ import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
@@ -243,7 +237,6 @@ import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.volume.VolumeComponent;
import java.io.FileDescriptor;
@@ -251,6 +244,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Map;
+import java.util.Optional;
import javax.inject.Named;
@@ -364,8 +358,6 @@ public class StatusBar extends SystemUI implements DemoMode,
@Nullable
private final KeyguardLiftController mKeyguardLiftController;
- private int mNaturalBarHeight = -1;
-
private final Point mCurrentDisplaySize = new Point();
protected StatusBarWindowViewController mStatusBarWindowViewController;
@@ -384,7 +376,6 @@ public class StatusBar extends SystemUI implements DemoMode,
private final FeatureFlags mFeatureFlags;
private final StatusBarIconController mIconController;
private final DozeLog mDozeLog;
- private final InjectionInflationController mInjectionInflater;
private final PulseExpansionHandler mPulseExpansionHandler;
private final NotificationWakeUpCoordinator mWakeUpCoordinator;
private final KeyguardBypassController mKeyguardBypassController;
@@ -403,6 +394,9 @@ public class StatusBar extends SystemUI implements DemoMode,
private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
private final PluginManager mPluginManager;
private final RemoteInputUriController mRemoteInputUriController;
+ private final Optional<Divider> mDividerOptional;
+ private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
+ private final LightsOutNotifController mLightsOutNotifController;
// expanded notifications
protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -637,8 +631,9 @@ public class StatusBar extends SystemUI implements DemoMode,
* Public constructor for StatusBar.
*
* StatusBar is considered optional, and therefore can not be marked as @Inject directly.
- * Instead, an @Provide method is included in {@link SystemUIBinder}.
+ * Instead, an @Provide method is included.
*/
+ @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public StatusBar(
Context context,
FeatureFlags featureFlags,
@@ -647,7 +642,6 @@ public class StatusBar extends SystemUI implements DemoMode,
KeyguardUpdateMonitor keyguardUpdateMonitor,
StatusBarIconController statusBarIconController,
DozeLog dozeLog,
- InjectionInflationController injectionInflationController,
PulseExpansionHandler pulseExpansionHandler,
NotificationWakeUpCoordinator notificationWakeUpCoordinator,
KeyguardBypassController keyguardBypassController,
@@ -706,7 +700,10 @@ public class StatusBar extends SystemUI implements DemoMode,
DozeScrimController dozeScrimController,
CommandQueue commandQueue,
PluginManager pluginManager,
- RemoteInputUriController remoteInputUriController) {
+ RemoteInputUriController remoteInputUriController,
+ Optional<Divider> dividerOptional,
+ LightsOutNotifController lightsOutNotifController,
+ SuperStatusBarViewFactory superStatusBarViewFactory) {
super(context);
mFeatureFlags = featureFlags;
mLightBarController = lightBarController;
@@ -714,7 +711,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mIconController = statusBarIconController;
mDozeLog = dozeLog;
- mInjectionInflater = injectionInflationController;
mPulseExpansionHandler = pulseExpansionHandler;
mWakeUpCoordinator = notificationWakeUpCoordinator;
mKeyguardBypassController = keyguardBypassController;
@@ -774,6 +770,10 @@ public class StatusBar extends SystemUI implements DemoMode,
mCommandQueue = commandQueue;
mPluginManager = pluginManager;
mRemoteInputUriController = remoteInputUriController;
+ mDividerOptional = dividerOptional;
+
+ mSuperStatusBarViewFactory = superStatusBarViewFactory;
+ mLightsOutNotifController = lightsOutNotifController;
mBubbleExpandListener =
(isExpanding, key) -> {
mEntryManager.updateNotifications("onBubbleExpandChanged");
@@ -860,19 +860,11 @@ public class StatusBar extends SystemUI implements DemoMode,
// Set up the initial notification state. This needs to happen before CommandQueue.disable()
setUpPresenter();
- if ((result.mSystemUiVisibility & View.STATUS_BAR_TRANSIENT) != 0) {
+ if (containsType(result.mTransientBarTypes, TYPE_TOP_BAR)) {
showTransientUnchecked();
}
- final int fullscreenAppearance = getAppearance(result.mFullscreenStackSysUiVisibility);
- final int dockedAppearance = getAppearance(result.mDockedStackSysUiVisibility);
- final AppearanceRegion[] appearanceRegions = result.mDockedStackBounds.isEmpty()
- ? new AppearanceRegion[]{
- new AppearanceRegion(fullscreenAppearance, result.mFullscreenStackBounds)}
- : new AppearanceRegion[]{
- new AppearanceRegion(fullscreenAppearance, result.mFullscreenStackBounds),
- new AppearanceRegion(dockedAppearance, result.mDockedStackBounds)};
- onSystemBarAppearanceChanged(mDisplayId, getAppearance(result.mSystemUiVisibility),
- appearanceRegions, result.mNavbarColorManagedByIme);
+ onSystemBarAppearanceChanged(mDisplayId, result.mAppearance, result.mAppearanceRegions,
+ result.mNavbarColorManagedByIme);
mAppFullscreen = result.mAppFullscreen;
mAppImmersive = result.mAppImmersive;
@@ -892,7 +884,7 @@ public class StatusBar extends SystemUI implements DemoMode,
"init: icons=%d disabled=0x%08x lights=0x%08x imeButton=0x%08x",
numIcons,
result.mDisabledFlags1,
- result.mSystemUiVisibility,
+ result.mAppearance,
result.mImeWindowVis));
}
@@ -935,7 +927,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mConfigurationController.addCallback(this);
// set the initial view visibility
- Dependency.get(InitController.class).addPostInitTask(this::updateAreThereNotifications);
int disabledFlags1 = result.mDisabledFlags1;
int disabledFlags2 = result.mDisabledFlags2;
Dependency.get(InitController.class).addPostInitTask(
@@ -1064,8 +1055,10 @@ public class StatusBar extends SystemUI implements DemoMode,
mStatusBarStateController, mKeyguardBypassController,
mKeyguardStateController, mWakeUpCoordinator, mCommandQueue);
mHeadsUpAppearanceController.readFrom(oldController);
+
+ mLightsOutNotifController.setLightsOutNotifView(
+ mStatusBarView.findViewById(R.id.notification_lights_out));
mStatusBarWindowViewController.setStatusBarView(mStatusBarView);
- updateAreThereNotifications();
checkBarModes();
}).getFragmentManager()
.beginTransaction()
@@ -1368,10 +1361,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
private void inflateShelf() {
- mNotificationShelf =
- (NotificationShelf) mInjectionInflater.injectable(
- LayoutInflater.from(mContext)).inflate(
- R.layout.status_bar_notification_shelf, mStackScroller, false);
+ mNotificationShelf = mSuperStatusBarViewFactory.getNotificationShelf(mStackScroller);
mNotificationShelf.setOnClickListener(mGoToLockedShadeListener);
}
@@ -1429,10 +1419,8 @@ public class StatusBar extends SystemUI implements DemoMode,
}
protected void inflateStatusBarWindow(Context context) {
- mStatusBarWindow = (StatusBarWindowView) mInjectionInflater.injectable(
- LayoutInflater.from(context)).inflate(R.layout.super_status_bar, null);
+ mStatusBarWindow = mSuperStatusBarViewFactory.getStatusBarWindowView();
mStatusBarWindowViewController = mStatusBarWindowViewControllerBuilder
- .setStatusBarWindowView(mStatusBarWindow)
.setShadeController(this)
.build();
}
@@ -1470,12 +1458,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
public int getStatusBarHeight() {
- if (mNaturalBarHeight < 0) {
- final Resources res = mContext.getResources();
- mNaturalBarHeight =
- res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
- }
- return mNaturalBarHeight;
+ return mStatusBarWindowController.getStatusBarHeight();
}
protected boolean toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) {
@@ -1493,8 +1476,8 @@ public class StatusBar extends SystemUI implements DemoMode,
: SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
return mRecents.splitPrimaryTask(createMode, null, metricsDockAction);
} else {
- Divider divider = getComponent(Divider.class);
- if (divider != null) {
+ if (mDividerOptional.isPresent()) {
+ Divider divider = mDividerOptional.get();
if (divider.isMinimized() && !divider.isHomeStackResizable()) {
// Undocking from the minimized state is not supported
return false;
@@ -1563,38 +1546,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- public void updateAreThereNotifications() {
- if (SPEW) {
- final boolean clearable = hasActiveNotifications() &&
- mNotificationPanel.hasActiveClearableNotifications();
- Log.d(TAG, "updateAreThereNotifications: N=" +
- mEntryManager.getNotificationData().getActiveNotifications().size() + " any=" +
- hasActiveNotifications() + " clearable=" + clearable);
- }
-
- if (mStatusBarView != null) {
- final View nlo = mStatusBarView.findViewById(R.id.notification_lights_out);
- final boolean showDot = hasActiveNotifications() && !areLightsOn();
- if (showDot != (nlo.getAlpha() == 1.0f)) {
- if (showDot) {
- nlo.setAlpha(0f);
- nlo.setVisibility(View.VISIBLE);
- }
- nlo.animate()
- .alpha(showDot ? 1 : 0)
- .setDuration(showDot ? 750 : 250)
- .setInterpolator(new AccelerateInterpolator(2.0f))
- .setListener(showDot ? null : new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator _a) {
- nlo.setVisibility(View.GONE);
- }
- })
- .start();
- }
- }
- }
-
private void updateReportRejectedTouchVisibility() {
if (mReportRejectedTouch == null) {
return;
@@ -2323,14 +2274,8 @@ public class StatusBar extends SystemUI implements DemoMode,
return;
}
boolean barModeChanged = false;
- final int diff = mAppearance ^ appearance;
if (mAppearance != appearance) {
mAppearance = appearance;
-
- // update low profile
- if ((diff & APPEARANCE_LOW_PROFILE_BARS) != 0) {
- updateAreThereNotifications();
- }
barModeChanged = updateBarMode(barMode(mTransientShown, appearance));
}
mLightBarController.onStatusBarAppearanceChanged(appearanceRegions, barModeChanged,
@@ -2511,10 +2456,6 @@ public class StatusBar extends SystemUI implements DemoMode,
return mAppImmersive;
}
- private boolean areLightsOn() {
- return 0 == (mAppearance & APPEARANCE_LOW_PROFILE_BARS);
- }
-
public static String viewInfo(View v) {
return "[(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom()
+ ") " + v.getWidth() + "x" + v.getHeight() + "]";
@@ -2649,7 +2590,7 @@ public class StatusBar extends SystemUI implements DemoMode,
public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
makeStatusBarView(result);
- mStatusBarWindowController.add(mStatusBarWindow, getStatusBarHeight());
+ mStatusBarWindowController.attach();
}
// called by makeStatusbar and also by PhoneStatusBarView
@@ -2927,7 +2868,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mQSPanel.updateResources();
}
- loadDimens();
+ mStatusBarWindowController.refreshStatusBarHeight();
if (mStatusBarView != null) {
mStatusBarView.updateResources();
@@ -2940,19 +2881,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
- protected void loadDimens() {
- final Resources res = mContext.getResources();
-
- int oldBarHeight = mNaturalBarHeight;
- mNaturalBarHeight = res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
- if (mStatusBarWindowController != null && mNaturalBarHeight != oldBarHeight) {
- mStatusBarWindowController.setBarHeight(mNaturalBarHeight);
- }
-
- if (DEBUG) Log.v(TAG, "defineSlots");
- }
-
// Visibility reporting
protected void handleVisibleToUserChanged(boolean visibleToUser) {
@@ -3981,14 +3909,14 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void appTransitionCancelled(int displayId) {
if (displayId == mDisplayId) {
- getComponent(Divider.class).onAppTransitionFinished();
+ mDividerOptional.ifPresent(Divider::onAppTransitionFinished);
}
}
@Override
public void appTransitionFinished(int displayId) {
if (displayId == mDisplayId) {
- getComponent(Divider.class).onAppTransitionFinished();
+ mDividerOptional.ifPresent(Divider::onAppTransitionFinished);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
new file mode 100644
index 000000000000..2364c336b7b1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.util.DisplayMetrics;
+
+import androidx.annotation.Nullable;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.UiOffloadThread;
+import com.android.systemui.appops.AppOpsController;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.FeatureFlags;
+import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationViewHierarchyManager;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.StatusBarDependenciesModule;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.ZenModeController;
+
+import java.util.Optional;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger Module providing {@link StatusBar}.
+ */
+@Module(includes = {StatusBarDependenciesModule.class})
+public class StatusBarModule {
+ /**
+ * Provides our instance of StatusBar which is considered optional.
+ */
+ @Provides
+ @Singleton
+ static StatusBar provideStatusBar(
+ Context context,
+ FeatureFlags featureFlags,
+ LightBarController lightBarController,
+ AutoHideController autoHideController,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ StatusBarIconController statusBarIconController,
+ DozeLog dozeLog,
+ PulseExpansionHandler pulseExpansionHandler,
+ NotificationWakeUpCoordinator notificationWakeUpCoordinator,
+ KeyguardBypassController keyguardBypassController,
+ KeyguardStateController keyguardStateController,
+ HeadsUpManagerPhone headsUpManagerPhone,
+ DynamicPrivacyController dynamicPrivacyController,
+ BypassHeadsUpNotifier bypassHeadsUpNotifier,
+ @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
+ Lazy<NewNotifPipeline> newNotifPipeline,
+ FalsingManager falsingManager,
+ BroadcastDispatcher broadcastDispatcher,
+ RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
+ NotificationGutsManager notificationGutsManager,
+ NotificationLogger notificationLogger,
+ NotificationEntryManager notificationEntryManager,
+ NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationViewHierarchyManager notificationViewHierarchyManager,
+ ForegroundServiceController foregroundServiceController,
+ AppOpsController appOpsController,
+ KeyguardViewMediator keyguardViewMediator,
+ ZenModeController zenModeController,
+ NotificationAlertingManager notificationAlertingManager,
+ DisplayMetrics displayMetrics,
+ MetricsLogger metricsLogger,
+ UiOffloadThread uiOffloadThread,
+ NotificationMediaManager notificationMediaManager,
+ NotificationLockscreenUserManager lockScreenUserManager,
+ NotificationRemoteInputManager remoteInputManager,
+ UserSwitcherController userSwitcherController,
+ NetworkController networkController,
+ BatteryController batteryController,
+ SysuiColorExtractor colorExtractor,
+ ScreenLifecycle screenLifecycle,
+ WakefulnessLifecycle wakefulnessLifecycle,
+ SysuiStatusBarStateController statusBarStateController,
+ VibratorHelper vibratorHelper,
+ BubbleController bubbleController,
+ NotificationGroupManager groupManager,
+ NotificationGroupAlertTransferHelper groupAlertTransferHelper,
+ VisualStabilityManager visualStabilityManager,
+ DeviceProvisionedController deviceProvisionedController,
+ NavigationBarController navigationBarController,
+ AssistManager assistManager,
+ NotificationListener notificationListener,
+ ConfigurationController configurationController,
+ StatusBarWindowController statusBarWindowController,
+ StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder,
+ NotifLog notifLog,
+ DozeParameters dozeParameters,
+ ScrimController scrimController,
+ @Nullable KeyguardLiftController keyguardLiftController,
+ Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
+ Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+ DozeServiceHost dozeServiceHost,
+ PowerManager powerManager,
+ DozeScrimController dozeScrimController,
+ CommandQueue commandQueue,
+ PluginManager pluginManager,
+ RemoteInputUriController remoteInputUriController,
+ Optional<Divider> dividerOptional,
+ LightsOutNotifController lightsOutNotifController,
+ SuperStatusBarViewFactory superStatusBarViewFactory) {
+ return new StatusBar(
+ context,
+ featureFlags,
+ lightBarController,
+ autoHideController,
+ keyguardUpdateMonitor,
+ statusBarIconController,
+ dozeLog,
+ pulseExpansionHandler,
+ notificationWakeUpCoordinator,
+ keyguardBypassController,
+ keyguardStateController,
+ headsUpManagerPhone,
+ dynamicPrivacyController,
+ bypassHeadsUpNotifier,
+ allowNotificationLongPress,
+ newNotifPipeline,
+ falsingManager,
+ broadcastDispatcher,
+ remoteInputQuickSettingsDisabler,
+ notificationGutsManager,
+ notificationLogger,
+ notificationEntryManager,
+ notificationInterruptionStateProvider,
+ notificationViewHierarchyManager,
+ foregroundServiceController,
+ appOpsController,
+ keyguardViewMediator,
+ zenModeController,
+ notificationAlertingManager,
+ displayMetrics,
+ metricsLogger,
+ uiOffloadThread,
+ notificationMediaManager,
+ lockScreenUserManager,
+ remoteInputManager,
+ userSwitcherController,
+ networkController,
+ batteryController,
+ colorExtractor,
+ screenLifecycle,
+ wakefulnessLifecycle,
+ statusBarStateController,
+ vibratorHelper,
+ bubbleController,
+ groupManager,
+ groupAlertTransferHelper,
+ visualStabilityManager,
+ deviceProvisionedController,
+ navigationBarController,
+ assistManager,
+ notificationListener,
+ configurationController,
+ statusBarWindowController,
+ statusBarWindowViewControllerBuilder,
+ notifLog,
+ dozeParameters,
+ scrimController,
+ keyguardLiftController,
+ lockscreenWallpaperLazy,
+ biometricUnlockControllerLazy,
+ dozeServiceHost,
+ powerManager,
+ dozeScrimController,
+ commandQueue,
+ pluginManager,
+ remoteInputUriController,
+ dividerOptional,
+ lightsOutNotifController,
+ superStatusBarViewFactory);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 02e5ebfe5705..38ff86227733 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -79,7 +79,8 @@ import java.util.ArrayList;
public class StatusBarNotificationPresenter implements NotificationPresenter,
ConfigurationController.ConfigurationListener,
- NotificationRowBinderImpl.BindRowCallback {
+ NotificationRowBinderImpl.BindRowCallback,
+ CommandQueue.Callbacks {
private final LockscreenGestureLogger mLockscreenGestureLogger =
Dependency.get(LockscreenGestureLogger.class);
@@ -185,17 +186,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
Dependency.get(InitController.class).addPostInitTask(() -> {
NotificationEntryListener notificationEntryListener = new NotificationEntryListener() {
@Override
- public void onNotificationAdded(NotificationEntry entry) {
- // Recalculate the position of the sliding windows and the titles.
- mShadeController.updateAreThereNotifications();
- }
-
- @Override
- public void onPostEntryUpdated(NotificationEntry entry) {
- mShadeController.updateAreThereNotifications();
- }
-
- @Override
public void onEntryRemoved(
@Nullable NotificationEntry entry,
NotificationVisibility visibility,
@@ -333,7 +323,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
}
}
}
- mShadeController.updateAreThereNotifications();
}
public boolean hasActiveNotifications() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index ca7a936d58f7..2ecceba2116a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -41,11 +41,13 @@ import android.view.WindowManager.LayoutParams;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.MainResources;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.RemoteInputController.Callback;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -69,6 +71,7 @@ import javax.inject.Singleton;
public class StatusBarWindowController implements Callback, Dumpable, ConfigurationListener {
private static final String TAG = "StatusBarWindowController";
+ private static final boolean DEBUG = false;
private final Context mContext;
private final WindowManager mWindowManager;
@@ -83,7 +86,7 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
private LayoutParams mLp;
private boolean mHasTopUi;
private boolean mHasTopUiChanged;
- private int mBarHeight;
+ private int mBarHeight = -1;
private float mScreenBrightnessDoze;
private final State mCurrentState = new State();
private OtherwisedCollapsedListener mListener;
@@ -92,13 +95,17 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
mCallbacks = Lists.newArrayList();
private final SysuiColorExtractor mColorExtractor;
+ private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
+ private final Resources mResources;
@Inject
public StatusBarWindowController(Context context, WindowManager windowManager,
IActivityManager activityManager, DozeParameters dozeParameters,
StatusBarStateController statusBarStateController,
ConfigurationController configurationController,
- KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor) {
+ KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor,
+ SuperStatusBarViewFactory superStatusBarViewFactory,
+ @MainResources Resources resources) {
mContext = context;
mWindowManager = windowManager;
mActivityManager = activityManager;
@@ -108,6 +115,15 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
mLpChanged = new LayoutParams();
mKeyguardBypassController = keyguardBypassController;
mColorExtractor = colorExtractor;
+ mSuperStatusBarViewFactory = superStatusBarViewFactory;
+ mStatusBarView = mSuperStatusBarViewFactory.getStatusBarWindowView();
+ mResources = resources;
+
+ if (mBarHeight < 0) {
+ mBarHeight = mResources.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+ }
+
mLockScreenDisplayTimeout = context.getResources()
.getInteger(R.integer.config_lockScreenDisplayTimeout);
((SysuiStatusBarStateController) statusBarStateController)
@@ -149,20 +165,36 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
|| res.getBoolean(R.bool.config_enableLockScreenRotation);
}
+ public int getStatusBarHeight() {
+ return mBarHeight;
+ }
+
/**
- * Adds the status bar view to the window manager.
- *
- * @param statusBarView The view to add.
- * @param barHeight The height of the status bar in collapsed state.
+ * Rereads the status_bar_height from configuration and reapplys the current state if the height
+ * is different.
*/
- public void add(ViewGroup statusBarView, int barHeight) {
+ public void refreshStatusBarHeight() {
+ int heightFromConfig = mResources.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+
+ if (mBarHeight != heightFromConfig) {
+ mBarHeight = heightFromConfig;
+ apply(mCurrentState);
+ }
+ if (DEBUG) Log.v(TAG, "defineSlots");
+ }
+
+ /**
+ * Adds the status bar view to the window manager.
+ */
+ public void attach() {
// Now that the status bar window encompasses the sliding panel and its
// translucent backdrop, the entire thing is made TRANSLUCENT and is
// hardware-accelerated.
mLp = new LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
- barHeight,
+ mBarHeight,
LayoutParams.TYPE_STATUS_BAR,
LayoutParams.FLAG_NOT_FOCUSABLE
| LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
@@ -176,8 +208,6 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
mLp.setTitle("StatusBar");
mLp.packageName = mContext.getPackageName();
mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
- mStatusBarView = statusBarView;
- mBarHeight = barHeight;
mWindowManager.addView(mStatusBarView, mLp);
mLpChanged.copyFrom(mLp);
onThemeChanged();
@@ -534,11 +564,6 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
apply(mCurrentState);
}
- public void setBarHeight(int barHeight) {
- mBarHeight = barHeight;
- apply(mCurrentState);
- }
-
public void setForcePluginOpen(boolean forcePluginOpen) {
mCurrentState.forcePluginOpen = forcePluginOpen;
apply(mCurrentState);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
index b7ada5d35a08..f716443cbfe1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
@@ -43,6 +43,7 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -492,7 +493,8 @@ public class StatusBarWindowViewController {
private final DozeLog mDozeLog;
private final DozeParameters mDozeParameters;
private final CommandQueue mCommandQueue;
- private StatusBarWindowView mView;
+ private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
+ private final StatusBarWindowView mView;
@Inject
public Builder(
@@ -510,7 +512,8 @@ public class StatusBarWindowViewController {
StatusBarStateController statusBarStateController,
DozeLog dozeLog,
DozeParameters dozeParameters,
- CommandQueue commandQueue) {
+ CommandQueue commandQueue,
+ SuperStatusBarViewFactory superStatusBarViewFactory) {
mInjectionInflationController = injectionInflationController;
mCoordinator = coordinator;
mPulseExpansionHandler = pulseExpansionHandler;
@@ -526,14 +529,9 @@ public class StatusBarWindowViewController {
mDozeLog = dozeLog;
mDozeParameters = dozeParameters;
mCommandQueue = commandQueue;
- }
+ mSuperStatusBarViewFactory = superStatusBarViewFactory;
- /**
- * Provide {@link StatusBarWindowView} to attach this controller to.
- */
- public Builder setStatusBarWindowView(StatusBarWindowView view) {
- mView = view;
- return this;
+ mView = mSuperStatusBarViewFactory.getStatusBarWindowView();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index e42432142927..12d357731560 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -649,7 +649,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
}
private boolean hasAnySim() {
- int simCount = mPhone.getSimCount();
+ int simCount = mPhone.getActiveModemCount();
for (int i = 0; i < simCount; i++) {
int state = mPhone.getSimState(i);
if (state != TelephonyManager.SIM_STATE_ABSENT
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 075c6d40ca31..13c0db938ca0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -463,8 +463,11 @@ public class UserSwitcherController implements Dumpable {
}
private void listenForCallState() {
- TelephonyManager.from(mContext).listen(mPhoneStateListener,
- PhoneStateListener.LISTEN_CALL_STATE);
+ final TelephonyManager tele =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ if (tele != null) {
+ tele.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+ }
}
private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index 1dd48634615b..d8eaaa182722 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -145,6 +145,7 @@ public class CarrierTextControllerTest extends SysuiTestCase {
mCarrierTextCallbackInfo = new CarrierTextController.CarrierTextCallbackInfo("",
new CharSequence[]{}, false, new int[]{});
when(mTelephonyManager.getSupportedModemCount()).thenReturn(3);
+ when(mTelephonyManager.getActiveModemCount()).thenReturn(3);
mCarrierTextController = new CarrierTextController(mContext, SEPARATOR, true, true);
// This should not start listening on any of the real dependencies but will test that
@@ -216,6 +217,15 @@ public class CarrierTextControllerTest extends SysuiTestCase {
// There's only one subscription in the list
assertEquals(1, captor.getValue().listOfCarriers.length);
assertEquals(TEST_CARRIER, captor.getValue().listOfCarriers[0]);
+
+ // Now it becomes single SIM active mode.
+ reset(mCarrierTextCallback);
+ when(mTelephonyManager.getActiveModemCount()).thenReturn(1);
+ // Update carrier text. It should ignore error state of subId 3 in inactive slotId.
+ mCarrierTextController.updateCarrierText();
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+ assertEquals("TEST_CARRIER", captor.getValue().carrierText);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index c215a43e0f3e..486fa12e0577 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -35,6 +35,7 @@ import android.app.ActivityManager;
import android.app.IActivityTaskManager;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.hardware.biometrics.Authenticator;
@@ -403,6 +404,19 @@ public class AuthControllerTest extends SysuiTestCase {
mAuthController.onDeviceCredentialPressed();
}
+ @Test
+ public void testActionCloseSystemDialogs_dismissesDialogIfShowing() throws Exception {
+ showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+ Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ mAuthController.mBroadcastReceiver.onReceive(mContext, intent);
+ waitForIdleSync();
+
+ assertNull(mAuthController.mCurrentDialog);
+ assertNull(mAuthController.mReceiver);
+ verify(mDialog1).dismissWithoutCallback(true /* animate */);
+ verify(mReceiver).onDialogDismissed(eq(BiometricPrompt.DISMISSED_REASON_USER_CANCEL));
+ }
+
// Helpers
private void showDialog(int authenticators, int biometricModality) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 00681130074b..b1a6bc6d41fd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -46,18 +46,19 @@ import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Resources;
import android.graphics.drawable.Icon;
import android.hardware.face.FaceManager;
import android.service.notification.ZenModeConfig;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.WindowManager;
-import android.widget.FrameLayout;
import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.systemui.R;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -65,6 +66,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -81,6 +83,7 @@ import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.util.InjectionInflationController;
import org.junit.Before;
import org.junit.Test;
@@ -119,7 +122,6 @@ public class BubbleControllerTest extends SysuiTestCase {
@Mock
private KeyguardBypassController mKeyguardBypassController;
- private FrameLayout mStatusBarView;
@Captor
private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
@Captor
@@ -147,22 +149,28 @@ public class BubbleControllerTest extends SysuiTestCase {
private SysuiColorExtractor mColorExtractor;
@Mock
ColorExtractor.GradientColors mGradientColors;
+ @Mock
+ private Resources mResources;
+ private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
private BubbleData mBubbleData;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mStatusBarView = new FrameLayout(mContext);
mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager);
mContext.addMockSystemService(FaceManager.class, mFaceManager);
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
+ mSuperStatusBarViewFactory = new SuperStatusBarViewFactory(mContext,
+ new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()));
+
// Bubbles get added to status bar window view
mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
mActivityManager, mDozeParameters, mStatusBarStateController,
- mConfigurationController, mKeyguardBypassController, mColorExtractor);
- mStatusBarWindowController.add(mStatusBarView, 120 /* height */);
+ mConfigurationController, mKeyguardBypassController, mColorExtractor,
+ mSuperStatusBarViewFactory, mResources);
+ mStatusBarWindowController.attach();
// Need notifications for bubbles
mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java
index 187c72a065a7..e4c387a26fd5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java
@@ -19,7 +19,10 @@ package com.android.systemui.keyguard;
import static android.app.ActivityManager.TaskDescription;
import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.annotation.ColorInt;
@@ -36,7 +39,6 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.keyguard.WorkLockActivity;
import org.junit.Before;
import org.junit.Test;
@@ -112,4 +114,11 @@ public class WorkLockActivityTest extends SysuiTestCase {
.putExtra(Intent.EXTRA_USER_ID, USER_ID));
assertEquals(orgColor, mActivity.getPrimaryColor());
}
+
+ @Test
+ public void testUnregisteredFromDispatcher() {
+ mActivity.unregisterBroadcastReceiver();
+ verify(mBroadcastDispatcher).unregisterReceiver(any());
+ verify(mContext, never()).unregisterReceiver(any());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
new file mode 100644
index 000000000000..99850e7c922e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.screenshot;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.graphics.Bitmap;
+import android.os.Handler;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SystemUIFactory;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+/**
+ * Tests for exception handling and bitmap configuration in adding smart actions to Screenshot
+ * Notification.
+ */
+public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
+ private ScreenshotNotificationSmartActionsProvider mSmartActionsProvider;
+ private Handler mHandler;
+
+ @Before
+ public void setup() {
+ mSmartActionsProvider = mock(
+ ScreenshotNotificationSmartActionsProvider.class);
+ mHandler = mock(Handler.class);
+ }
+
+ // Tests any exception thrown in getting smart actions future does not affect regular
+ // screenshot flow.
+ @Test
+ public void testExceptionHandlingInGetSmartActionsFuture()
+ throws Exception {
+ Bitmap bitmap = mock(Bitmap.class);
+ when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
+ ScreenshotNotificationSmartActionsProvider smartActionsProvider = mock(
+ ScreenshotNotificationSmartActionsProvider.class);
+ when(smartActionsProvider.getActions(any(), any(), any(), any(), any(),
+ eq(false))).thenThrow(
+ RuntimeException.class);
+ CompletableFuture<List<Notification.Action>> smartActionsFuture =
+ GlobalScreenshot.getSmartActionsFuture(mContext, bitmap,
+ smartActionsProvider, mHandler, true, false);
+ Assert.assertNotNull(smartActionsFuture);
+ List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
+ Assert.assertEquals(Collections.emptyList(), smartActions);
+ }
+
+ // Tests any exception thrown in waiting for smart actions future to complete does
+ // not affect regular screenshot flow.
+ @Test
+ public void testExceptionHandlingInGetSmartActions()
+ throws Exception {
+ CompletableFuture<List<Notification.Action>> smartActionsFuture = mock(
+ CompletableFuture.class);
+ int timeoutMs = 1000;
+ when(smartActionsFuture.get(timeoutMs, TimeUnit.MILLISECONDS)).thenThrow(
+ RuntimeException.class);
+ List<Notification.Action> actions = GlobalScreenshot.getSmartActions(
+ smartActionsFuture, timeoutMs);
+ Assert.assertEquals(Collections.emptyList(), actions);
+ }
+
+ // Tests for a non-hardware bitmap, ScreenshotNotificationSmartActionsProvider is never invoked
+ // and a completed future is returned.
+ @Test
+ public void testUnsupportedBitmapConfiguration()
+ throws Exception {
+ Bitmap bitmap = mock(Bitmap.class);
+ when(bitmap.getConfig()).thenReturn(Bitmap.Config.RGB_565);
+ CompletableFuture<List<Notification.Action>> smartActionsFuture =
+ GlobalScreenshot.getSmartActionsFuture(mContext, bitmap,
+ mSmartActionsProvider, mHandler, true, true);
+ verify(mSmartActionsProvider, never()).getActions(any(), any(), any(), any(), any(),
+ eq(false));
+ Assert.assertNotNull(smartActionsFuture);
+ List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
+ Assert.assertEquals(Collections.emptyList(), smartActions);
+ }
+
+ // Tests for a hardware bitmap, ScreenshotNotificationSmartActionsProvider is invoked once.
+ @Test
+ public void testScreenshotNotificationSmartActionsProviderInvokedOnce() {
+ Bitmap bitmap = mock(Bitmap.class);
+ when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
+ GlobalScreenshot.getSmartActionsFuture(mContext, bitmap, mSmartActionsProvider,
+ mHandler, true, true);
+ verify(mSmartActionsProvider, times(1))
+ .getActions(any(), any(), any(), any(), any(), eq(true));
+ }
+
+ // Tests for a hardware bitmap, a completed future is returned.
+ @Test
+ public void testSupportedBitmapConfiguration()
+ throws Exception {
+ Bitmap bitmap = mock(Bitmap.class);
+ when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
+ ScreenshotNotificationSmartActionsProvider actionsProvider =
+ SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider();
+ CompletableFuture<List<Notification.Action>> smartActionsFuture =
+ GlobalScreenshot.getSmartActionsFuture(mContext, bitmap,
+ actionsProvider,
+ mHandler, true, true);
+ Assert.assertNotNull(smartActionsFuture);
+ List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
+ Assert.assertEquals(smartActions.size(), 0);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index cf6fd4a3380f..d9be8d85850e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -34,8 +34,11 @@ import android.app.admin.DevicePolicyManager;
import android.app.trust.TrustManager;
import android.content.Context;
import android.graphics.Color;
+import android.hardware.biometrics.BiometricSourceType;
+import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Looper;
+import android.os.UserManager;
import android.view.View;
import android.view.ViewGroup;
@@ -51,6 +54,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.AccessibilityController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.wakelock.WakeLockFake;
@@ -84,6 +88,10 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
private StatusBarStateController mStatusBarStateController;
@Mock
private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ @Mock
+ private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ @Mock
+ private UserManager mUserManager;
private KeyguardIndicationTextView mTextView;
private KeyguardIndicationController mController;
@@ -97,9 +105,13 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
mTextView = new KeyguardIndicationTextView(mContext);
mContext.addMockSystemService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManager);
+ mContext.addMockSystemService(UserManager.class, mUserManager);
mContext.addMockSystemService(Context.TRUST_SERVICE, mock(TrustManager.class));
mContext.addMockSystemService(Context.FINGERPRINT_SERVICE, mock(FingerprintManager.class));
+ when(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
+ when(mKeyguardUpdateMonitor.isScreenOn()).thenReturn(true);
+ when(mKeyguardUpdateMonitor.isUserUnlocked(anyInt())).thenReturn(true);
when(mIndicationArea.findViewById(R.id.keyguard_indication_text)).thenReturn(mTextView);
mWakeLock = new WakeLockFake();
@@ -112,6 +124,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
mController = new KeyguardIndicationController(mContext, mIndicationArea, mLockIcon,
mLockPatternUtils, mWakeLock, mShadeController, mAccessibilityController,
mKeyguardStateController, mStatusBarStateController, mKeyguardUpdateMonitor);
+ mController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
}
@Test
@@ -167,6 +180,49 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
}
@Test
+ public void transientIndication_visibleWhenDozing_unlessSwipeUp_fromHelp() {
+ createController();
+ String message = "A message";
+
+ mController.setVisible(true);
+ mController.getKeyguardCallback().onBiometricHelp(
+ KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED, message,
+ BiometricSourceType.FACE);
+ assertThat(mTextView.getText()).isEqualTo(message);
+ mController.setDozing(true);
+
+ assertThat(mTextView.getText()).isNotEqualTo(message);
+ }
+
+ @Test
+ public void transientIndication_visibleWhenDozing_unlessSwipeUp_fromError() {
+ createController();
+ String message = mContext.getString(R.string.keyguard_unlock);
+
+ mController.setVisible(true);
+ mController.getKeyguardCallback().onBiometricError(FaceManager.FACE_ERROR_TIMEOUT,
+ "A message", BiometricSourceType.FACE);
+
+ assertThat(mTextView.getText()).isEqualTo(message);
+ mController.setDozing(true);
+
+ assertThat(mTextView.getText()).isNotEqualTo(message);
+ }
+
+ @Test
+ public void transientIndication_swipeUpToRetry() {
+ createController();
+ String message = mContext.getString(R.string.keyguard_retry);
+ when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(true);
+
+ mController.setVisible(true);
+ mController.getKeyguardCallback().onBiometricError(FaceManager.FACE_ERROR_TIMEOUT,
+ "A message", BiometricSourceType.FACE);
+
+ verify(mStatusBarKeyguardViewManager).showBouncerMessage(eq(message), any());
+ }
+
+ @Test
public void lockIcon_click() {
createController();
@@ -190,6 +246,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
public void updateMonitor_listenerUpdatesIndication() {
createController();
String restingIndication = "Resting indication";
+ reset(mKeyguardUpdateMonitor);
mController.setVisible(true);
assertThat(mTextView.getText()).isEqualTo(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index 5e6c96313d36..d17c573515f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -226,7 +226,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
any(NotificationMenuRowPlugin.MenuItem.class));
reset(listener);
- mGroupRow.setDismissed(true);
+ mGroupRow.dismiss(true);
mGroupRow.doLongClickCallback(0,0);
verify(listener, times(0)).onLongPress(eq(mGroupRow), eq(0), eq(0),
any(NotificationMenuRowPlugin.MenuItem.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java
new file mode 100644
index 000000000000..64c1b510cbf9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.Display;
+import android.view.View;
+import android.view.ViewPropertyAnimator;
+import android.view.WindowManager;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.notification.NotificationEntryListener;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotificationData;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public class LightsOutNotifControllerTest extends SysuiTestCase {
+ private static final int LIGHTS_ON = 0;
+ private static final int LIGHTS_OUT = APPEARANCE_LOW_PROFILE_BARS;
+
+ @Mock private NotificationEntryManager mEntryManager;
+ @Mock private NotificationData mNotificationData;
+ @Mock private CommandQueue mCommandQueue;
+ @Mock private WindowManager mWindowManager;
+ @Mock private Display mDisplay;
+
+ @Captor private ArgumentCaptor<NotificationEntryListener> mListenerCaptor;
+ @Captor private ArgumentCaptor<CommandQueue.Callbacks> mCallbacksCaptor;
+
+ private View mLightsOutView;
+ private LightsOutNotifController mLightsOutNotifController;
+ private ArrayList<NotificationEntry> mActiveNotifications = new ArrayList<>();
+ private int mDisplayId;
+ private NotificationEntryListener mEntryListener;
+ private CommandQueue.Callbacks mCallbacks;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mDisplayId = mContext.getDisplayId();
+ mLightsOutView = new View(mContext);
+ when(mEntryManager.getNotificationData()).thenReturn(mNotificationData);
+ when(mNotificationData.getActiveNotifications()).thenReturn(mActiveNotifications);
+ when(mWindowManager.getDefaultDisplay()).thenReturn(mDisplay);
+ when(mDisplay.getDisplayId()).thenReturn(mDisplayId);
+
+ mLightsOutNotifController = new LightsOutNotifController(mWindowManager, mEntryManager,
+ mCommandQueue);
+ mLightsOutNotifController.setLightsOutNotifView(mLightsOutView);
+
+ // Capture the entry listener object so we can simulate events in tests below
+ verify(mEntryManager).addNotificationEntryListener(mListenerCaptor.capture());
+ mEntryListener = checkNotNull(mListenerCaptor.getValue());
+
+ // Capture the callback object so we can simulate callback events in tests below
+ verify(mCommandQueue).addCallback(mCallbacksCaptor.capture());
+ mCallbacks = checkNotNull(mCallbacksCaptor.getValue());
+ }
+
+ @Test
+ public void testAreLightsOut_lightsOut() {
+ mCallbacks.onSystemBarAppearanceChanged(
+ mDisplayId /* display id */,
+ LIGHTS_OUT /* appearance */,
+ null /* appearanceRegions */,
+ false /* navbarColorManagedByIme */);
+ assertTrue(mLightsOutNotifController.areLightsOut());
+ }
+
+ @Test
+ public void testAreLightsOut_lightsOn() {
+ mCallbacks.onSystemBarAppearanceChanged(
+ mDisplayId /* display id */,
+ LIGHTS_ON /* appearance */,
+ null /* appearanceRegions */,
+ false /* navbarColorManagedByIme */);
+ assertFalse(mLightsOutNotifController.areLightsOut());
+ }
+
+ @Test
+ public void testIsShowingDot_visible() {
+ mLightsOutView.setVisibility(View.VISIBLE);
+ mLightsOutView.setAlpha(1.0f);
+ assertTrue(mLightsOutNotifController.isShowingDot());
+ }
+
+ @Test
+ public void testIsShowingDot_gone() {
+ mLightsOutView.setVisibility(View.GONE);
+ mLightsOutView.setAlpha(0f);
+ assertFalse(mLightsOutNotifController.isShowingDot());
+ }
+
+ @Test
+ public void testLightsOut_withNotifs_onSystemBarAppearanceChanged() {
+ // GIVEN active visible notifications
+ mActiveNotifications.add(mock(NotificationEntry.class));
+
+ // WHEN lights out
+ mCallbacks.onSystemBarAppearanceChanged(
+ mDisplayId /* display id */,
+ LIGHTS_OUT /* appearance */,
+ null /* appearanceRegions */,
+ false /* navbarColorManagedByIme */);
+
+ // THEN we should show dot
+ assertTrue(mLightsOutNotifController.shouldShowDot());
+ assertIsShowingDot(true);
+ }
+
+ @Test
+ public void testLightsOut_withoutNotifs_onSystemBarAppearanceChanged() {
+ // GIVEN no active visible notifications
+ mActiveNotifications.clear();
+
+ // WHEN lights out
+ mCallbacks.onSystemBarAppearanceChanged(
+ mDisplayId /* display id */,
+ LIGHTS_OUT /* appearance */,
+ null /* appearanceRegions */,
+ false /* navbarColorManagedByIme */);
+
+ // THEN we shouldn't show the dot
+ assertFalse(mLightsOutNotifController.shouldShowDot());
+ assertIsShowingDot(false);
+ }
+
+ @Test
+ public void testLightsOn_afterLightsOut_onSystemBarAppearanceChanged() {
+ // GIVEN active visible notifications
+ mActiveNotifications.add(mock(NotificationEntry.class));
+
+ // WHEN lights on
+ mCallbacks.onSystemBarAppearanceChanged(
+ mDisplayId /* display id */,
+ LIGHTS_ON /* appearance */,
+ null /* appearanceRegions */,
+ false /* navbarColorManagedByIme */);
+
+ // THEN we shouldn't show the dot
+ assertFalse(mLightsOutNotifController.shouldShowDot());
+ assertIsShowingDot(false);
+ }
+
+ @Test
+ public void testEntryAdded() {
+ // GIVEN no visible notifications and lights out
+ mActiveNotifications.clear();
+ mLightsOutNotifController.mAppearance = LIGHTS_OUT;
+ mLightsOutNotifController.updateLightsOutView();
+ assertIsShowingDot(false);
+
+ // WHEN an active notification is added
+ mActiveNotifications.add(mock(NotificationEntry.class));
+ assertTrue(mLightsOutNotifController.shouldShowDot());
+ mEntryListener.onNotificationAdded(mock(NotificationEntry.class));
+
+ // THEN we should see the dot view
+ assertIsShowingDot(true);
+ }
+
+ @Test
+ public void testEntryRemoved() {
+ // GIVEN a visible notification and lights out
+ mActiveNotifications.add(mock(NotificationEntry.class));
+ mLightsOutNotifController.mAppearance = LIGHTS_OUT;
+ mLightsOutNotifController.updateLightsOutView();
+ assertIsShowingDot(true);
+
+ // WHEN all active notifications are removed
+ mActiveNotifications.clear();
+ assertFalse(mLightsOutNotifController.shouldShowDot());
+ mEntryListener.onEntryRemoved(mock(NotificationEntry.class), null, false);
+
+ // THEN we shouldn't see the dot view
+ assertIsShowingDot(false);
+ }
+
+ @Test
+ public void testEntryUpdated() {
+ // GIVEN no visible notifications and lights out
+ mActiveNotifications.clear();
+ mLightsOutNotifController.mAppearance = LIGHTS_OUT;
+ mLightsOutNotifController.updateLightsOutView();
+ assertIsShowingDot(false);
+
+ // WHEN an active notification is added
+ mActiveNotifications.add(mock(NotificationEntry.class));
+ assertTrue(mLightsOutNotifController.shouldShowDot());
+ mEntryListener.onPostEntryUpdated(mock(NotificationEntry.class));
+
+ // THEN we should see the dot view
+ assertIsShowingDot(true);
+ }
+
+ private void assertIsShowingDot(boolean isShowing) {
+ // cancel the animation so we can check the end state
+ final ViewPropertyAnimator animation = mLightsOutView.animate();
+ if (animation != null) {
+ animation.cancel();
+ }
+
+ if (isShowing) {
+ assertTrue(mLightsOutNotifController.isShowingDot());
+ } else {
+ assertFalse(mLightsOutNotifController.isShowingDot());
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index 125500178d30..9763675df6bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -79,6 +79,8 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Optional;
+
@RunWith(AndroidTestingRunner.class)
@RunWithLooper(setAsMainLooper = true)
@SmallTest
@@ -95,6 +97,10 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest {
private SysUiState mMockSysUiState;
@Mock
private BroadcastDispatcher mBroadcastDispatcher;
+ @Mock
+ private Divider mDivider;
+ @Mock
+ private Recents mRecents;
private AccessibilityManagerWrapper mAccessibilityWrapper =
new AccessibilityManagerWrapper(mContext) {
@@ -152,16 +158,12 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest {
private void setupSysuiDependency() {
mSysuiContext.putComponent(StatusBar.class, mock(StatusBar.class));
- mSysuiContext.putComponent(Recents.class, mock(Recents.class));
- mSysuiContext.putComponent(Divider.class, mock(Divider.class));
Display display = new Display(DisplayManagerGlobal.getInstance(), EXTERNAL_DISPLAY_ID,
new DisplayInfo(), DEFAULT_DISPLAY_ADJUSTMENTS);
mSysuiTestableContextExternal = (SysuiTestableContext) mSysuiContext.createDisplayContext(
display);
mSysuiTestableContextExternal.putComponent(StatusBar.class, mock(StatusBar.class));
- mSysuiTestableContextExternal.putComponent(Recents.class, mock(Recents.class));
- mSysuiTestableContextExternal.putComponent(Divider.class, mock(Divider.class));
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
WindowManager windowManager = mock(WindowManager.class);
@@ -251,7 +253,9 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest {
mock(StatusBarStateController.class),
mMockSysUiState,
mBroadcastDispatcher,
- mCommandQueue);
+ mCommandQueue,
+ mDivider,
+ Optional.of(mRecents));
}
private class HostCallbacksForExternalDisplay extends
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index c21e3ab079ff..7d6f006eb833 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -92,6 +92,7 @@ import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -107,6 +108,7 @@ import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
@@ -134,7 +136,6 @@ import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.util.InjectionInflationController;
import org.junit.Before;
import org.junit.Test;
@@ -145,6 +146,7 @@ import org.mockito.MockitoAnnotations;
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Optional;
import dagger.Lazy;
@@ -208,7 +210,6 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private PulseExpansionHandler mPulseExpansionHandler;
@Mock private NotificationWakeUpCoordinator mNotificationWakeUpCoordinator;
@Mock private KeyguardBypassController mKeyguardBypassController;
- @Mock private InjectionInflationController mInjectionInflationController;
@Mock private DynamicPrivacyController mDynamicPrivacyController;
@Mock private NewNotifPipeline mNewNotifPipeline;
@Mock private ZenModeController mZenModeController;
@@ -234,6 +235,9 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private KeyguardLiftController mKeyguardLiftController;
@Mock private CommandQueue mCommandQueue;
@Mock private PluginManager mPluginManager;
+ @Mock private Divider mDivider;
+ @Mock private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
+ @Mock private LightsOutNotifController mLightsOutNotifController;
@Before
public void setup() throws Exception {
@@ -309,7 +313,6 @@ public class StatusBarTest extends SysuiTestCase {
mKeyguardUpdateMonitor,
mStatusBarIconController,
mDozeLog,
- mInjectionInflationController,
mPulseExpansionHandler,
mNotificationWakeUpCoordinator,
mKeyguardBypassController,
@@ -372,7 +375,10 @@ public class StatusBarTest extends SysuiTestCase {
mDozeScrimController,
mCommandQueue,
mPluginManager,
- mRemoteInputUriController);
+ mRemoteInputUriController,
+ Optional.of(mDivider),
+ mLightsOutNotifController,
+ mSuperStatusBarViewFactory);
when(mStatusBarWindowView.findViewById(R.id.lock_icon_container)).thenReturn(
mLockIconContainer);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
index a21a658348c4..147edf6589e9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
@@ -25,9 +25,9 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.IActivityManager;
+import android.content.res.Resources;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
-import android.view.ViewGroup;
import android.view.WindowManager;
import androidx.test.filters.SmallTest;
@@ -35,6 +35,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -52,13 +53,15 @@ public class StatusBarWindowControllerTest extends SysuiTestCase {
@Mock private WindowManager mWindowManager;
@Mock private DozeParameters mDozeParameters;
- @Mock private ViewGroup mStatusBarView;
+ @Mock private StatusBarWindowView mStatusBarView;
@Mock private IActivityManager mActivityManager;
@Mock private SysuiStatusBarStateController mStatusBarStateController;
@Mock private ConfigurationController mConfigurationController;
@Mock private KeyguardBypassController mKeyguardBypassController;
@Mock private SysuiColorExtractor mColorExtractor;
@Mock ColorExtractor.GradientColors mGradientColors;
+ @Mock private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
+ @Mock private Resources mResources;
private StatusBarWindowController mStatusBarWindowController;
@@ -67,11 +70,14 @@ public class StatusBarWindowControllerTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
when(mDozeParameters.getAlwaysOn()).thenReturn(true);
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
+ when(mSuperStatusBarViewFactory.getStatusBarWindowView()).thenReturn(mStatusBarView);
mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
mActivityManager, mDozeParameters, mStatusBarStateController,
- mConfigurationController, mKeyguardBypassController, mColorExtractor);
- mStatusBarWindowController.add(mStatusBarView, 100 /* height */);
+ mConfigurationController, mKeyguardBypassController, mColorExtractor,
+ mSuperStatusBarViewFactory, mResources);
+
+ mStatusBarWindowController.attach();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
index 20fb6599f66e..bf81325eb6f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
@@ -35,6 +35,7 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -72,6 +73,7 @@ public class StatusBarWindowViewTest extends SysuiTestCase {
@Mock private StatusBar mStatusBar;
@Mock private DozeLog mDozeLog;
@Mock private DozeParameters mDozeParameters;
+ @Mock private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
@Before
public void setUp() {
@@ -82,6 +84,8 @@ public class StatusBarWindowViewTest extends SysuiTestCase {
when(mStatusBar.isDozing()).thenReturn(false);
mDependency.injectTestDependency(ShadeController.class, mShadeController);
+ when(mSuperStatusBarViewFactory.getStatusBarWindowView()).thenReturn(mView);
+
mController = new StatusBarWindowViewController.Builder(
new InjectionInflationController(
SystemUIFactory.getInstance().getRootComponent()),
@@ -98,9 +102,9 @@ public class StatusBarWindowViewTest extends SysuiTestCase {
mStatusBarStateController,
mDozeLog,
mDozeParameters,
- new CommandQueue(mContext))
+ new CommandQueue(mContext),
+ mSuperStatusBarViewFactory)
.setShadeController(mShadeController)
- .setStatusBarWindowView(mView)
.build();
mController.setService(mStatusBar);
mController.setDragDownHelper(mDragDownHelper);
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index 998572fc5679..61bfb92363bd 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -27,6 +27,7 @@ java_defaults {
"androidx.annotation_annotation",
"netd_aidl_interface-java",
"networkstack-aidl-interfaces-java",
+ "android.hardware.tetheroffload.control-V1.0-java",
"tethering-client",
],
manifest: "AndroidManifestBase.xml",
@@ -38,11 +39,39 @@ android_library {
defaults: ["TetheringAndroidLibraryDefaults"],
}
+cc_library_shared {
+ name: "libtetheroffloadjni",
+ srcs: [
+ "jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp",
+ ],
+ shared_libs: [
+ "libnativehelper",
+ "libcutils",
+ "android.hardware.tetheroffload.config@1.0",
+ ],
+ static_libs: [
+ "liblog",
+ "libbase",
+ "libhidlbase",
+ "libutils",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wthread-safety",
+ ],
+}
+
// Common defaults for compiling the actual APK.
java_defaults {
name: "TetheringAppDefaults",
platform_apis: true,
privileged: true,
+ jni_libs: [
+ "libtetheroffloadjni",
+ ],
resource_dirs: [
"res",
],
@@ -71,6 +100,8 @@ filegroup {
name: "tethering-servicescore-srcs",
srcs: [
"src/com/android/server/connectivity/tethering/EntitlementManager.java",
+ "src/com/android/server/connectivity/tethering/OffloadController.java",
+ "src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java",
"src/com/android/server/connectivity/tethering/TetheringConfiguration.java",
"src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java",
],
@@ -88,3 +119,11 @@ filegroup {
"src/android/net/util/PrefixUtils.java",
],
}
+
+// This group would be removed when tethering migration is done.
+filegroup {
+ name: "tethering-jni-srcs",
+ srcs: [
+ "jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp",
+ ],
+}
diff --git a/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp b/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
index 3eaf48845a2f..3eaf48845a2f 100644
--- a/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
+++ b/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
index a3c299814a7a..16734d83e3aa 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
@@ -36,8 +36,8 @@ import android.net.netlink.NetlinkSocket;
import android.net.util.IpUtils;
import android.net.util.SharedLog;
import android.os.Handler;
-import android.os.Looper;
import android.os.INetworkManagementService;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.Settings;
@@ -60,7 +60,6 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
/**
* A class to encapsulate the business logic of programming the tethering
@@ -74,7 +73,7 @@ public class OffloadController {
private static final String ANYIP = "0.0.0.0";
private static final ForwardedStats EMPTY_STATS = new ForwardedStats();
- private static enum UpdateType { IF_NEEDED, FORCE };
+ private enum UpdateType { IF_NEEDED, FORCE };
private final Handler mHandler;
private final OffloadHardwareInterface mHwInterface;
@@ -128,6 +127,7 @@ public class OffloadController {
}
}
+ /** Start hardware offload. */
public boolean start() {
if (started()) return true;
@@ -235,6 +235,7 @@ public class OffloadController {
return isStarted;
}
+ /** Stop hardware offload. */
public void stop() {
// Completely stops tethering offload. After this method is called, it is no longer safe to
// call any HAL method, no callbacks from the hardware will be delivered, and any in-flight
@@ -258,7 +259,9 @@ public class OffloadController {
// getTetherStats() is the only function in OffloadController that can be called from
// a different thread. Do not attempt to update stats by querying the offload HAL
// synchronously from a different thread than our Handler thread. http://b/64771555.
- Runnable updateStats = () -> { updateStatsForCurrentUpstream(); };
+ Runnable updateStats = () -> {
+ updateStatsForCurrentUpstream();
+ };
if (Looper.myLooper() == mHandler.getLooper()) {
updateStats.run();
} else {
@@ -358,6 +361,7 @@ public class OffloadController {
}
}
+ /** Set current tethering upstream LinkProperties. */
public void setUpstreamLinkProperties(LinkProperties lp) {
if (!started() || Objects.equals(mUpstreamLinkProperties, lp)) return;
@@ -376,6 +380,7 @@ public class OffloadController {
pushUpstreamParameters(prevUpstream);
}
+ /** Set local prefixes. */
public void setLocalPrefixes(Set<IpPrefix> localPrefixes) {
mExemptPrefixes = localPrefixes;
@@ -383,6 +388,7 @@ public class OffloadController {
computeAndPushLocalPrefixes(UpdateType.IF_NEEDED);
}
+ /** Update current downstream LinkProperties. */
public void notifyDownstreamLinkProperties(LinkProperties lp) {
final String ifname = lp.getInterfaceName();
final LinkProperties oldLp = mDownstreams.put(ifname, new LinkProperties(lp));
@@ -421,6 +427,7 @@ public class OffloadController {
}
}
+ /** Remove downstream interface from offload hardware. */
public void removeDownstreamInterface(String ifname) {
final LinkProperties lp = mDownstreams.remove(ifname);
if (lp == null) return;
@@ -481,7 +488,7 @@ public class OffloadController {
iface, v4addr, v4gateway, (v6gateways.isEmpty() ? null : v6gateways));
if (!success) {
- return success;
+ return success;
}
// Update stats after we've told the hardware to change routing so we don't miss packets.
@@ -545,6 +552,7 @@ public class OffloadController {
return false;
}
+ /** Dump information. */
public void dump(IndentingPrintWriter pw) {
if (isOffloadDisabled()) {
pw.println("Offload disabled");
@@ -630,7 +638,7 @@ public class OffloadController {
if (ip instanceof Inet4Address) {
return (Inet4Address) ip;
}
- } catch (IllegalArgumentException iae) {}
+ } catch (IllegalArgumentException iae) { }
return null;
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
index 207f86762b95..01339a4a2c33 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
@@ -23,9 +23,9 @@ import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback;
import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
+import android.net.util.SharedLog;
import android.os.Handler;
import android.os.RemoteException;
-import android.net.util.SharedLog;
import android.system.OsConstants;
import java.util.ArrayList;
@@ -55,18 +55,34 @@ public class OffloadHardwareInterface {
private TetheringOffloadCallback mTetheringOffloadCallback;
private ControlCallback mControlCallback;
+ /** The callback to notify status of offload management process. */
public static class ControlCallback {
+ /** Offload started. */
public void onStarted() {}
+ /**
+ * Offload stopped because an error has occurred in lower layer.
+ */
public void onStoppedError() {}
+ /**
+ * Offload stopped because the device has moved to a bearer on which hardware offload is
+ * not supported. Subsequent calls to setUpstreamParameters and add/removeDownstream will
+ * likely fail and cannot be presumed to be saved inside of the hardware management process.
+ * Upon receiving #onSupportAvailable(), the caller should reprogram the hardware to begin
+ * offload again.
+ */
public void onStoppedUnsupported() {}
+ /** Indicate that offload is able to proivde support for this time. */
public void onSupportAvailable() {}
+ /** Offload stopped because of usage limit reached. */
public void onStoppedLimitReached() {}
+ /** Indicate to update NAT timeout. */
public void onNatTimeoutUpdate(int proto,
String srcAddr, int srcPort,
String dstAddr, int dstPort) {}
}
+ /** The object which records Tx/Rx forwarded bytes. */
public static class ForwardedStats {
public long rxBytes;
public long txBytes;
@@ -76,11 +92,13 @@ public class OffloadHardwareInterface {
txBytes = 0;
}
+ /** Add Tx/Rx bytes. */
public void add(ForwardedStats other) {
rxBytes += other.rxBytes;
txBytes += other.txBytes;
}
+ /** Returns the string representation of this object. */
public String toString() {
return String.format("rx:%s tx:%s", rxBytes, txBytes);
}
@@ -91,14 +109,17 @@ public class OffloadHardwareInterface {
mLog = log.forSubComponent(TAG);
}
+ /** Get default value indicating whether offload is supported. */
public int getDefaultTetherOffloadDisabled() {
return DEFAULT_TETHER_OFFLOAD_DISABLED;
}
+ /** Configure offload management process. */
public boolean initOffloadConfig() {
return configOffload();
}
+ /** Initialize the tethering offload HAL. */
public boolean initOffloadControl(ControlCallback controlCb) {
mControlCallback = controlCb;
@@ -125,8 +146,8 @@ public class OffloadHardwareInterface {
mOffloadControl.initOffload(
mTetheringOffloadCallback,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -134,9 +155,10 @@ public class OffloadHardwareInterface {
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
+ /** Stop IOffloadControl. */
public void stopOffloadControl() {
if (mOffloadControl != null) {
try {
@@ -154,6 +176,7 @@ public class OffloadHardwareInterface {
mLog.log("stopOffloadControl()");
}
+ /** Get Tx/Rx usage from last query. */
public ForwardedStats getForwardedStats(String upstream) {
final String logmsg = String.format("getForwardedStats(%s)", upstream);
@@ -174,6 +197,7 @@ public class OffloadHardwareInterface {
return stats;
}
+ /** Set local prefixes to offload management process. */
public boolean setLocalPrefixes(ArrayList<String> localPrefixes) {
final String logmsg = String.format("setLocalPrefixes([%s])",
String.join(",", localPrefixes));
@@ -182,8 +206,8 @@ public class OffloadHardwareInterface {
try {
mOffloadControl.setLocalPrefixes(localPrefixes,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -191,9 +215,10 @@ public class OffloadHardwareInterface {
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
+ /** Set data limit value to offload management process. */
public boolean setDataLimit(String iface, long limit) {
final String logmsg = String.format("setDataLimit(%s, %d)", iface, limit);
@@ -203,8 +228,8 @@ public class OffloadHardwareInterface {
mOffloadControl.setDataLimit(
iface, limit,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -212,9 +237,10 @@ public class OffloadHardwareInterface {
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
+ /** Set upstream parameters to offload management process. */
public boolean setUpstreamParameters(
String iface, String v4addr, String v4gateway, ArrayList<String> v6gws) {
iface = (iface != null) ? iface : NO_INTERFACE_NAME;
@@ -230,8 +256,8 @@ public class OffloadHardwareInterface {
mOffloadControl.setUpstreamParameters(
iface, v4addr, v4gateway, v6gws,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -239,9 +265,10 @@ public class OffloadHardwareInterface {
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
+ /** Add downstream prefix to offload management process. */
public boolean addDownstreamPrefix(String ifname, String prefix) {
final String logmsg = String.format("addDownstreamPrefix(%s, %s)", ifname, prefix);
@@ -249,8 +276,8 @@ public class OffloadHardwareInterface {
try {
mOffloadControl.addDownstream(ifname, prefix,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -258,9 +285,10 @@ public class OffloadHardwareInterface {
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
+ /** Remove downstream prefix from offload management process. */
public boolean removeDownstreamPrefix(String ifname, String prefix) {
final String logmsg = String.format("removeDownstreamPrefix(%s, %s)", ifname, prefix);
@@ -268,8 +296,8 @@ public class OffloadHardwareInterface {
try {
mOffloadControl.removeDownstream(ifname, prefix,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -277,7 +305,7 @@ public class OffloadHardwareInterface {
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
private void record(String msg, Throwable t) {
@@ -286,7 +314,7 @@ public class OffloadHardwareInterface {
private void record(String msg, CbResults results) {
final String logmsg = msg + YIELDS + results;
- if (!results.success) {
+ if (!results.mSuccess) {
mLog.e(logmsg);
} else {
mLog.log(logmsg);
@@ -298,7 +326,7 @@ public class OffloadHardwareInterface {
public final ControlCallback controlCb;
public final SharedLog log;
- public TetheringOffloadCallback(Handler h, ControlCallback cb, SharedLog sharedLog) {
+ TetheringOffloadCallback(Handler h, ControlCallback cb, SharedLog sharedLog) {
handler = h;
controlCb = cb;
log = sharedLog;
@@ -332,7 +360,7 @@ public class OffloadHardwareInterface {
@Override
public void updateTimeout(NatTimeoutUpdate params) {
handler.post(() -> {
- controlCb.onNatTimeoutUpdate(
+ controlCb.onNatTimeoutUpdate(
networkProtocolToOsConstant(params.proto),
params.src.addr, uint16(params.src.port),
params.dst.addr, uint16(params.dst.port));
@@ -352,15 +380,15 @@ public class OffloadHardwareInterface {
}
private static class CbResults {
- boolean success;
- String errMsg;
+ boolean mSuccess;
+ String mErrMsg;
@Override
public String toString() {
- if (success) {
+ if (mSuccess) {
return "ok";
} else {
- return "fail: " + errMsg;
+ return "fail: " + mErrMsg;
}
}
}
diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp
index 7c06e5f0d7ce..363be18a73bc 100644
--- a/packages/Tethering/tests/unit/Android.bp
+++ b/packages/Tethering/tests/unit/Android.bp
@@ -25,6 +25,7 @@ android_test {
static_libs: [
"androidx.test.rules",
"frameworks-base-testutils",
+ "net-tests-utils",
"mockito-target-extended-minus-junit4",
"TetheringApiCurrentLib",
"testables",
@@ -46,6 +47,7 @@ filegroup {
name: "tethering-tests-src",
srcs: [
"src/com/android/server/connectivity/tethering/EntitlementManagerTest.java",
+ "src/com/android/server/connectivity/tethering/OffloadControllerTest.java",
"src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java",
"src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java",
"src/android/net/dhcp/DhcpServingParamsParcelExtTest.java",
diff --git a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
index 9931aec01487..8574f5401496 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
@@ -26,10 +26,10 @@ import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
import static com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats;
import static com.android.testutils.MiscAssertsKt.assertContainsAll;
+import static com.android.testutils.MiscAssertsKt.assertThrows;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
@@ -148,10 +148,8 @@ public class OffloadControllerTest {
public void testNoSettingsValueDefaultDisabledDoesNotStart() throws Exception {
setupFunctioningHardwareInterface();
when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(1);
- try {
- Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED);
- fail();
- } catch (SettingNotFoundException expected) {}
+ assertThrows(SettingNotFoundException.class, () ->
+ Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED));
final OffloadController offload = makeOffloadController();
offload.start();
@@ -168,10 +166,8 @@ public class OffloadControllerTest {
public void testNoSettingsValueDefaultEnabledDoesStart() throws Exception {
setupFunctioningHardwareInterface();
when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(0);
- try {
- Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED);
- fail();
- } catch (SettingNotFoundException expected) {}
+ assertThrows(SettingNotFoundException.class, () ->
+ Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED));
final OffloadController offload = makeOffloadController();
offload.start();
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 1fc47516864b..3cbfcf118363 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -40,6 +40,10 @@ import android.service.autofill.InternalValidator;
import android.service.autofill.SaveInfo;
import android.service.autofill.ValueFinder;
import android.text.Html;
+import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
@@ -60,11 +64,14 @@ import android.widget.TextView;
import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.util.ArrayUtils;
import com.android.server.UiThread;
import com.android.server.autofill.Helper;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
/**
* Autofill Save Prompt
@@ -158,6 +165,7 @@ final class SaveUi {
private final ComponentName mComponentName;
private final boolean mCompatMode;
private final int mThemeId;
+ private final int mType;
private boolean mDestroyed;
@@ -179,8 +187,17 @@ final class SaveUi {
context = new ContextThemeWrapper(context, mThemeId) {
@Override
public void startActivity(Intent intent) {
+ if (intent.resolveActivity(getPackageManager()) == null) {
+ return;
+ }
+ intent.putExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY, true);
+
PendingIntent p = PendingIntent.getActivity(this, 0, intent, 0);
- mListener.startIntentSender(p.getIntentSender(), intent);
+ if (sDebug) {
+ Slog.d(TAG, "startActivity add save UI restored with intent=" + intent);
+ }
+ // Apply restore mechanism
+ startIntentSenderWithRestore(p, intent);
}
};
final LayoutInflater inflater = LayoutInflater.from(context);
@@ -189,12 +206,12 @@ final class SaveUi {
final TextView titleView = view.findViewById(R.id.autofill_save_title);
final ArraySet<String> types = new ArraySet<>(3);
- final int type = info.getType();
+ mType = info.getType();
- if ((type & SaveInfo.SAVE_DATA_TYPE_PASSWORD) != 0) {
+ if ((mType & SaveInfo.SAVE_DATA_TYPE_PASSWORD) != 0) {
types.add(context.getString(R.string.autofill_save_type_password));
}
- if ((type & SaveInfo.SAVE_DATA_TYPE_ADDRESS) != 0) {
+ if ((mType & SaveInfo.SAVE_DATA_TYPE_ADDRESS) != 0) {
types.add(context.getString(R.string.autofill_save_type_address));
}
@@ -202,20 +219,20 @@ final class SaveUi {
final int cardTypeMask = SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD
| SaveInfo.SAVE_DATA_TYPE_DEBIT_CARD
| SaveInfo.SAVE_DATA_TYPE_PAYMENT_CARD;
- final int count = Integer.bitCount(type & cardTypeMask);
- if (count > 1 || (type & SaveInfo.SAVE_DATA_TYPE_GENERIC_CARD) != 0) {
+ final int count = Integer.bitCount(mType & cardTypeMask);
+ if (count > 1 || (mType & SaveInfo.SAVE_DATA_TYPE_GENERIC_CARD) != 0) {
types.add(context.getString(R.string.autofill_save_type_generic_card));
- } else if ((type & SaveInfo.SAVE_DATA_TYPE_PAYMENT_CARD) != 0) {
+ } else if ((mType & SaveInfo.SAVE_DATA_TYPE_PAYMENT_CARD) != 0) {
types.add(context.getString(R.string.autofill_save_type_payment_card));
- } else if ((type & SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD) != 0) {
+ } else if ((mType & SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD) != 0) {
types.add(context.getString(R.string.autofill_save_type_credit_card));
- } else if ((type & SaveInfo.SAVE_DATA_TYPE_DEBIT_CARD) != 0) {
+ } else if ((mType & SaveInfo.SAVE_DATA_TYPE_DEBIT_CARD) != 0) {
types.add(context.getString(R.string.autofill_save_type_debit_card));
}
- if ((type & SaveInfo.SAVE_DATA_TYPE_USERNAME) != 0) {
+ if ((mType & SaveInfo.SAVE_DATA_TYPE_USERNAME) != 0) {
types.add(context.getString(R.string.autofill_save_type_username));
}
- if ((type & SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS) != 0) {
+ if ((mType & SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS) != 0) {
types.add(context.getString(R.string.autofill_save_type_email_address));
}
@@ -257,11 +274,12 @@ final class SaveUi {
} else {
mSubTitle = info.getDescription();
if (mSubTitle != null) {
- writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_SUBTITLE, type);
+ writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_SUBTITLE);
final ViewGroup subtitleContainer =
view.findViewById(R.id.autofill_save_custom_subtitle);
final TextView subtitleView = new TextView(context);
subtitleView.setText(mSubTitle);
+ applyMovementMethodIfNeed(subtitleView);
subtitleContainer.addView(subtitleView,
new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
@@ -318,8 +336,7 @@ final class SaveUi {
if (customDescription == null) {
return false;
}
- final int type = info.getType();
- writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_DESCRIPTION, type);
+ writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_DESCRIPTION);
final RemoteViews template = customDescription.getPresentation();
if (template == null) {
@@ -342,26 +359,15 @@ final class SaveUi {
final RemoteViews.OnClickHandler handler = (view, pendingIntent, response) -> {
Intent intent = response.getLaunchOptions(view).first;
- final LogMaker log =
- newLogMaker(MetricsEvent.AUTOFILL_SAVE_LINK_TAPPED, type);
- // We need to hide the Save UI before launching the pending intent, and
- // restore back it once the activity is finished, and that's achieved by
- // adding a custom extra in the activity intent.
final boolean isValid = isValidLink(pendingIntent, intent);
if (!isValid) {
+ final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_SAVE_LINK_TAPPED, mType);
log.setType(MetricsEvent.TYPE_UNKNOWN);
mMetricsLogger.write(log);
return false;
}
- if (sVerbose) Slog.v(TAG, "Intercepting custom description intent");
- final IBinder token = mPendingUi.getToken();
- intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
- mListener.startIntentSender(pendingIntent.getIntentSender(), intent);
- mPendingUi.setState(PendingUi.STATE_PENDING);
- if (sDebug) Slog.d(TAG, "hiding UI until restored with token " + token);
- hide();
- log.setType(MetricsEvent.TYPE_OPEN);
- mMetricsLogger.write(log);
+
+ startIntentSenderWithRestore(pendingIntent, intent);
return true;
};
@@ -442,6 +448,8 @@ final class SaveUi {
}
}
+ applyTextViewStyle(customSubtitleView);
+
// Finally, add the custom description to the save UI.
final ViewGroup subtitleContainer =
saveUiView.findViewById(R.id.autofill_save_custom_subtitle);
@@ -457,6 +465,60 @@ final class SaveUi {
return false;
}
+ private void startIntentSenderWithRestore(@NonNull PendingIntent pendingIntent,
+ @NonNull Intent intent) {
+ if (sVerbose) Slog.v(TAG, "Intercepting custom description intent");
+
+ // We need to hide the Save UI before launching the pending intent, and
+ // restore back it once the activity is finished, and that's achieved by
+ // adding a custom extra in the activity intent.
+ final IBinder token = mPendingUi.getToken();
+ intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
+
+ mListener.startIntentSender(pendingIntent.getIntentSender(), intent);
+ mPendingUi.setState(PendingUi.STATE_PENDING);
+
+ if (sDebug) Slog.d(TAG, "hiding UI until restored with token " + token);
+ hide();
+
+ final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_SAVE_LINK_TAPPED, mType);
+ log.setType(MetricsEvent.TYPE_OPEN);
+ mMetricsLogger.write(log);
+ }
+
+ private void applyTextViewStyle(@NonNull View rootView) {
+ final List<TextView> textViews = new ArrayList<>();
+ final Predicate<View> predicate = (view) -> {
+ if (view instanceof TextView) {
+ // Collects TextViews
+ textViews.add((TextView) view);
+ }
+ return false;
+ };
+
+ // Traverses all TextViews, enables movement method if the TextView contains URLSpan
+ rootView.findViewByPredicate(predicate);
+ final int size = textViews.size();
+ for (int i = 0; i < size; i++) {
+ applyMovementMethodIfNeed(textViews.get(i));
+ }
+ }
+
+ private void applyMovementMethodIfNeed(@NonNull TextView textView) {
+ final CharSequence message = textView.getText();
+ if (TextUtils.isEmpty(message)) {
+ return;
+ }
+
+ final SpannableStringBuilder ssb = new SpannableStringBuilder(message);
+ final ClickableSpan[] spans = ssb.getSpans(0, ssb.length(), ClickableSpan.class);
+ if (ArrayUtils.isEmpty(spans)) {
+ return;
+ }
+
+ textView.setMovementMethod(LinkMovementMethod.getInstance());
+ }
+
private void setServiceIcon(Context context, View view, Drawable serviceIcon) {
final ImageView iconView = view.findViewById(R.id.autofill_save_icon);
final Resources res = context.getResources();
@@ -506,8 +568,8 @@ final class SaveUi {
mPendingUi.sessionId, mCompatMode);
}
- private void writeLog(int category, int saveType) {
- mMetricsLogger.write(newLogMaker(category, saveType));
+ private void writeLog(int category) {
+ mMetricsLogger.write(newLogMaker(category, mType));
}
/**
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 067becbf0c52..8f1e1568ead6 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -335,6 +335,16 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
return new ComponentNameSet(setting).contains(component);
}
+ @Override
+ public boolean isDeviceAssociated(String packageName, String macAddress, int userId) {
+ getContext().enforceCallingOrSelfPermission(
+ android.Manifest.permission.MANAGE_COMPANION_DEVICES, "isDeviceAssociated");
+
+ return CollectionUtils.any(
+ readAllAssociations(userId, packageName),
+ a -> Objects.equals(a.deviceAddress, macAddress));
+ }
+
private void checkCanCallNotificationApi(String callingPackage) throws RemoteException {
checkCallerIsSystemOr(callingPackage);
int userId = getCallingUserId();
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
index ecea251cc1ac..9cdb58d8c019 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
@@ -16,7 +16,6 @@
package com.android.server.contentsuggestions;
-import static android.Manifest.permission.BIND_CONTENT_SUGGESTIONS_SERVICE;
import static android.Manifest.permission.MANAGE_CONTENT_SUGGESTIONS;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -96,7 +95,7 @@ public class ContentSuggestionsManagerService extends
private void enforceCaller(int userId, String func) {
Context ctx = getContext();
- if (ctx.checkCallingPermission(BIND_CONTENT_SUGGESTIONS_SERVICE) == PERMISSION_GRANTED
+ if (ctx.checkCallingPermission(MANAGE_CONTENT_SUGGESTIONS) == PERMISSION_GRANTED
|| mServiceNameResolver.isTemporary(userId)
|| mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid())) {
return;
diff --git a/services/core/java/com/android/server/AlarmManagerInternal.java b/services/core/java/com/android/server/AlarmManagerInternal.java
index 5b0de5e2aae0..0a735029eead 100644
--- a/services/core/java/com/android/server/AlarmManagerInternal.java
+++ b/services/core/java/com/android/server/AlarmManagerInternal.java
@@ -16,6 +16,8 @@
package com.android.server;
+import android.app.PendingIntent;
+
public interface AlarmManagerInternal {
// Some other components in the system server need to know about
// broadcast alarms currently in flight
@@ -30,4 +32,10 @@ public interface AlarmManagerInternal {
boolean isIdling();
public void removeAlarmsForUid(int uid);
public void registerInFlightListener(InFlightListener callback);
+
+ /**
+ * Removes any alarm with the given pending intent with equality determined using
+ * {@link android.app.PendingIntent#equals(java.lang.Object) PendingIntent.equals}
+ */
+ void remove(PendingIntent rec);
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index e757b4e1a070..e4d477a03afc 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -213,7 +213,6 @@ class AlarmManagerService extends SystemService {
IAlarmListener mTimeTickTrigger;
PendingIntent mDateChangeSender;
Random mRandom;
- PendingIntent.CancelListener mOperationCancelListener;
boolean mInteractive = true;
long mNonInteractiveStartTime;
long mNonInteractiveTime;
@@ -1460,7 +1459,6 @@ class AlarmManagerService extends SystemService {
synchronized (mLock) {
mHandler = new AlarmHandler();
- mOperationCancelListener = (intent) -> removeImpl(intent, null);
mConstants = new Constants(mHandler);
mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW);
@@ -1715,9 +1713,6 @@ class AlarmManagerService extends SystemService {
} else {
maxElapsed = triggerElapsed + windowLength;
}
- if (operation != null) {
- operation.registerCancelListener(mOperationCancelListener);
- }
synchronized (mLock) {
if (DEBUG_BATCH) {
Slog.v(TAG, "set(" + operation + ") : type=" + type
@@ -1730,8 +1725,6 @@ class AlarmManagerService extends SystemService {
"Maximum limit of concurrent alarms " + mConstants.MAX_ALARMS_PER_UID
+ " reached for uid: " + UserHandle.formatUid(callingUid)
+ ", callingPackage: " + callingPackage;
- mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER,
- operation).sendToTarget();
Slog.w(TAG, errorMsg);
throw new IllegalStateException(errorMsg);
}
@@ -1752,8 +1745,6 @@ class AlarmManagerService extends SystemService {
if (ActivityManager.getService().isAppStartModeDisabled(callingUid, callingPackage)) {
Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a
+ " -- package not allowed to start");
- mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER,
- operation).sendToTarget();
return;
}
} catch (RemoteException e) {
@@ -1970,6 +1961,11 @@ class AlarmManagerService extends SystemService {
}
@Override
+ public void remove(PendingIntent pi) {
+ mHandler.obtainMessage(AlarmHandler.REMOVE_FOR_CANCELED, pi).sendToTarget();
+ }
+
+ @Override
public void registerInFlightListener(InFlightListener callback) {
synchronized (mLock) {
mInFlightListeners.add(callback);
@@ -2074,8 +2070,6 @@ class AlarmManagerService extends SystemService {
synchronized (mLock) {
removeLocked(operation, listener);
}
- mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER,
- operation).sendToTarget();
}
@Override
@@ -4078,7 +4072,7 @@ class AlarmManagerService extends SystemService {
public static final int APP_STANDBY_BUCKET_CHANGED = 5;
public static final int CHARGING_STATUS_CHANGED = 6;
public static final int REMOVE_FOR_STOPPED = 7;
- public static final int UNREGISTER_CANCEL_LISTENER = 8;
+ public static final int REMOVE_FOR_CANCELED = 8;
AlarmHandler() {
super(Looper.myLooper());
@@ -4161,10 +4155,10 @@ class AlarmManagerService extends SystemService {
}
break;
- case UNREGISTER_CANCEL_LISTENER:
- final PendingIntent pi = (PendingIntent) msg.obj;
- if (pi != null) {
- pi.unregisterCancelListener(mOperationCancelListener);
+ case REMOVE_FOR_CANCELED:
+ final PendingIntent operation = (PendingIntent) msg.obj;
+ synchronized (mLock) {
+ removeLocked(operation, null);
}
break;
@@ -4644,11 +4638,6 @@ class AlarmManagerService extends SystemService {
Intent.EXTRA_ALARM_COUNT, alarm.count),
mDeliveryTracker, mHandler, null,
allowWhileIdle ? mIdleOptions : null);
- if (alarm.repeatInterval == 0) {
- // Keep the listener for repeating alarms until they get cancelled
- mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER,
- alarm.operation).sendToTarget();
- }
} catch (PendingIntent.CanceledException e) {
if (alarm.repeatInterval > 0) {
// This IntentSender is no longer valid, but this
diff --git a/services/core/java/com/android/server/AppStateTracker.java b/services/core/java/com/android/server/AppStateTracker.java
index 486cd5fee01c..7d5b17684843 100644
--- a/services/core/java/com/android/server/AppStateTracker.java
+++ b/services/core/java/com/android/server/AppStateTracker.java
@@ -699,14 +699,16 @@ public class AppStateTracker {
Slog.d(TAG,"onAppIdleStateChanged: " + packageName + " u" + userId
+ (idle ? " idle" : " active") + " " + bucket);
}
- final boolean changed;
- if (bucket == UsageStatsManager.STANDBY_BUCKET_EXEMPTED) {
- changed = mExemptedPackages.add(userId, packageName);
- } else {
- changed = mExemptedPackages.remove(userId, packageName);
- }
- if (changed) {
- mHandler.notifyExemptChanged();
+ synchronized (mLock) {
+ final boolean changed;
+ if (bucket == UsageStatsManager.STANDBY_BUCKET_EXEMPTED) {
+ changed = mExemptedPackages.add(userId, packageName);
+ } else {
+ changed = mExemptedPackages.remove(userId, packageName);
+ }
+ if (changed) {
+ mHandler.notifyExemptChanged();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 39f039af330c..e1f65979bec3 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -43,7 +43,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.content.res.Resources;
-import android.database.ContentObserver;
import android.hardware.location.ActivityRecognitionHardware;
import android.location.Address;
import android.location.Criteria;
@@ -79,7 +78,6 @@ import android.os.WorkSource.WorkChain;
import android.provider.Settings;
import android.stats.location.LocationStatsEnums;
import android.text.TextUtils;
-import android.util.ArraySet;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
@@ -99,12 +97,12 @@ import com.android.server.location.CallerIdentity;
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceManager;
import com.android.server.location.GeofenceProxy;
-import com.android.server.location.LocationBlacklist;
import com.android.server.location.LocationFudger;
import com.android.server.location.LocationProviderProxy;
import com.android.server.location.LocationRequestStatistics;
import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
import com.android.server.location.LocationRequestStatistics.PackageStatistics;
+import com.android.server.location.LocationSettingsStore;
import com.android.server.location.MockProvider;
import com.android.server.location.PassiveProvider;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
@@ -183,13 +181,6 @@ public class LocationManagerService extends ILocationManager.Stub {
private static final int FOREGROUND_IMPORTANCE_CUTOFF
= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
- // default background throttling interval if not overriden in settings
- private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
-
- // Default value for maximum age of last location returned to applications with foreground-only
- // location permissions.
- private static final long DEFAULT_LAST_LOCATION_MAX_AGE_MS = 20 * 60 * 1000;
-
// Location Providers may sometimes deliver location updates
// slightly faster that requested - provide grace period so
// we don't unnecessarily filter events that are otherwise on
@@ -208,13 +199,14 @@ public class LocationManagerService extends ILocationManager.Stub {
private ActivityManager mActivityManager;
private UserManager mUserManager;
+ private LocationSettingsStore mSettingsStore;
+
private GeofenceManager mGeofenceManager;
private LocationFudger mLocationFudger;
private GeocoderProxy mGeocodeProvider;
@Nullable
private GnssManagerService mGnssManagerService;
private PassiveProvider mPassiveProvider; // track passive provider for special cases
- private LocationBlacklist mBlacklist;
@GuardedBy("mLock")
private String mExtraLocationControllerPackage;
private boolean mExtraLocationControllerPackageEnabled;
@@ -245,10 +237,6 @@ public class LocationManagerService extends ILocationManager.Stub {
private final HashMap<String, Location> mLastLocationCoarseInterval =
new HashMap<>();
- private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
-
- private final ArraySet<String> mIgnoreSettingsPackageWhitelist = new ArraySet<>();
-
// current active user on the device - other users are denied location data
private int mCurrentUserId = UserHandle.USER_SYSTEM;
private int[] mCurrentUserProfiles = new int[]{UserHandle.USER_SYSTEM};
@@ -287,16 +275,19 @@ public class LocationManagerService extends ILocationManager.Stub {
@GuardedBy("mLock")
private void initializeLocked() {
- mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
mPackageManager = mContext.getPackageManager();
- mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
- mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mAppOps = mContext.getSystemService(AppOpsManager.class);
+ mPowerManager = mContext.getSystemService(PowerManager.class);
+ mActivityManager = mContext.getSystemService(ActivityManager.class);
+ mUserManager = mContext.getSystemService(UserManager.class);
+
+ mSettingsStore = new LocationSettingsStore(mContext, mHandler);
mLocationFudger = new LocationFudger(mContext, mHandler);
- mBlacklist = new LocationBlacklist(mContext, mHandler);
- mBlacklist.init();
- mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
+ mGeofenceManager = new GeofenceManager(mContext, mSettingsStore);
+
+ PowerManagerInternal localPowerManager =
+ LocalServices.getService(PowerManagerInternal.class);
// prepare providers
initializeProvidersLocked();
@@ -327,7 +318,6 @@ public class LocationManagerService extends ILocationManager.Stub {
}
});
});
-
mActivityManager.addOnUidImportanceListener(
(uid, importance) -> {
// listener invoked on ui thread, move to our thread to reduce risk of blocking
@@ -339,63 +329,7 @@ public class LocationManagerService extends ILocationManager.Stub {
});
},
FOREGROUND_IMPORTANCE_CUTOFF);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.LOCATION_MODE), true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onLocationModeChangedLocked(true);
- }
- }
- }, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onProviderAllowedChangedLocked();
- }
- }
- }, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onBackgroundThrottleIntervalChangedLocked();
- }
- }
- }, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onBackgroundThrottleWhitelistChangedLocked();
- }
- }
- }, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(
- Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onIgnoreSettingsWhitelistChangedLocked();
- }
- }
- }, UserHandle.USER_ALL);
- PowerManagerInternal localPowerManager =
- LocalServices.getService(PowerManagerInternal.class);
+
localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION,
state -> {
// listener invoked on ui thread, move to our thread to reduce risk of blocking
@@ -406,6 +340,33 @@ public class LocationManagerService extends ILocationManager.Stub {
}
});
});
+ mBatterySaverMode = mPowerManager.getLocationPowerSaveMode();
+
+ mSettingsStore.addOnLocationEnabledChangedListener(() -> {
+ synchronized (mLock) {
+ onLocationModeChangedLocked(true);
+ }
+ });
+ mSettingsStore.addOnLocationProvidersAllowedChangedListener(() -> {
+ synchronized (mLock) {
+ onProviderAllowedChangedLocked();
+ }
+ });
+ mSettingsStore.addOnBackgroundThrottleIntervalChangedListener(() -> {
+ synchronized (mLock) {
+ onBackgroundThrottleIntervalChangedLocked();
+ }
+ });
+ mSettingsStore.addOnBackgroundThrottlePackageWhitelistChangedListener(() -> {
+ synchronized (mLock) {
+ onBackgroundThrottleWhitelistChangedLocked();
+ }
+ });
+ mSettingsStore.addOnIgnoreSettingsPackageWhitelistChangedListener(() -> {
+ synchronized (mLock) {
+ onIgnoreSettingsWhitelistChangedLocked();
+ }
+ });
new PackageMonitor() {
@Override
@@ -453,11 +414,6 @@ public class LocationManagerService extends ILocationManager.Stub {
// provider initialization, and propagates changes until a steady state is reached
mCurrentUserId = UserHandle.USER_NULL;
onUserChangedLocked(ActivityManager.getCurrentUser());
-
- // initialize in-memory settings values
- onBackgroundThrottleWhitelistChangedLocked();
- onIgnoreSettingsWhitelistChangedLocked();
- onBatterySaverModeChangedLocked(mPowerManager.getLocationPowerSaveMode());
}
@GuardedBy("mLock")
@@ -479,6 +435,10 @@ public class LocationManagerService extends ILocationManager.Stub {
@GuardedBy("mLock")
private void onBatterySaverModeChangedLocked(int newLocationMode) {
+ if (mBatterySaverMode == newLocationMode) {
+ return;
+ }
+
if (D) {
Slog.d(TAG,
"Battery Saver location mode changed from "
@@ -486,11 +446,8 @@ public class LocationManagerService extends ILocationManager.Stub {
+ locationPowerSaveModeToString(newLocationMode));
}
- if (mBatterySaverMode == newLocationMode) {
- return;
- }
-
mBatterySaverMode = newLocationMode;
+
for (LocationProvider p : mProviders) {
applyRequirementsLocked(p);
}
@@ -588,17 +545,6 @@ public class LocationManagerService extends ILocationManager.Stub {
@GuardedBy("mLock")
private void onBackgroundThrottleWhitelistChangedLocked() {
- mBackgroundThrottlePackageWhitelist.clear();
- mBackgroundThrottlePackageWhitelist.addAll(
- SystemConfig.getInstance().getAllowUnthrottledLocation());
-
- String setting = Settings.Global.getString(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
- if (!TextUtils.isEmpty(setting)) {
- mBackgroundThrottlePackageWhitelist.addAll(Arrays.asList(setting.split(",")));
- }
-
for (LocationProvider p : mProviders) {
applyRequirementsLocked(p);
}
@@ -606,17 +552,6 @@ public class LocationManagerService extends ILocationManager.Stub {
@GuardedBy("lock")
private void onIgnoreSettingsWhitelistChangedLocked() {
- mIgnoreSettingsPackageWhitelist.clear();
- mIgnoreSettingsPackageWhitelist.addAll(
- SystemConfig.getInstance().getAllowIgnoreLocationSettings());
-
- String setting = Settings.Global.getString(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST);
- if (!TextUtils.isEmpty(setting)) {
- mIgnoreSettingsPackageWhitelist.addAll(Arrays.asList(setting.split(",")));
- }
-
for (LocationProvider p : mProviders) {
applyRequirementsLocked(p);
}
@@ -859,8 +794,6 @@ public class LocationManagerService extends ILocationManager.Stub {
mCurrentUserId = userId;
onUserProfilesChangedLocked();
- mBlacklist.switchUser(userId);
-
// if the user changes, per-user settings may also have changed
onLocationModeChangedLocked(false);
onProviderAllowedChangedLocked();
@@ -1083,11 +1016,8 @@ public class LocationManagerService extends ILocationManager.Stub {
@GuardedBy("mLock")
public void onAllowedChangedLocked() {
if (mIsManagedBySettings) {
- String allowedProviders = Settings.Secure.getStringForUser(
- mContext.getContentResolver(),
- Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
- mCurrentUserId);
- boolean allowed = TextUtils.delimitedStringContains(allowedProviders, ',', mName);
+ boolean allowed = mSettingsStore.getLocationProvidersAllowed(
+ mCurrentUserId).contains(mName);
if (allowed == mAllowed) {
return;
@@ -1909,10 +1839,7 @@ public class LocationManagerService extends ILocationManager.Stub {
long identity = Binder.clearCallingIdentity();
try {
- backgroundThrottleInterval = Settings.Global.getLong(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
- DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
+ backgroundThrottleInterval = mSettingsStore.getBackgroundThrottleIntervalMs();
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2032,16 +1959,12 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
public String[] getBackgroundThrottlingWhitelist() {
- synchronized (mLock) {
- return mBackgroundThrottlePackageWhitelist.toArray(new String[0]);
- }
+ return mSettingsStore.getBackgroundThrottlePackageWhitelist().toArray(new String[0]);
}
@Override
public String[] getIgnoreSettingsWhitelist() {
- synchronized (mLock) {
- return mIgnoreSettingsPackageWhitelist.toArray(new String[0]);
- }
+ return mSettingsStore.getIgnoreSettingsPackageWhitelist().toArray(new String[0]);
}
@GuardedBy("mLock")
@@ -2050,7 +1973,8 @@ public class LocationManagerService extends ILocationManager.Stub {
return true;
}
- if (mBackgroundThrottlePackageWhitelist.contains(callerIdentity.mPackageName)) {
+ if (mSettingsStore.getBackgroundThrottlePackageWhitelist().contains(
+ callerIdentity.mPackageName)) {
return true;
}
@@ -2064,7 +1988,7 @@ public class LocationManagerService extends ILocationManager.Stub {
return false;
}
- if (mIgnoreSettingsPackageWhitelist.contains(
+ if (mSettingsStore.getIgnoreSettingsPackageWhitelist().contains(
record.mReceiver.mCallerIdentity.mPackageName)) {
return true;
}
@@ -2081,23 +2005,13 @@ public class LocationManagerService extends ILocationManager.Stub {
private boolean mIsForegroundUid;
private Location mLastFixBroadcast;
private Throwable mStackTrace; // for debugging only
+ private long mExpirationRealtimeMs;
/**
* Note: must be constructed with lock held.
*/
private UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
- // translate expireIn value into expireAt
- long elapsedRealtime = SystemClock.elapsedRealtime();
- long expireAt;
- // Check for > Long.MAX_VALUE overflow (elapsedRealtime > 0):
- if (request.getExpireIn() > Long.MAX_VALUE - elapsedRealtime) {
- expireAt = Long.MAX_VALUE;
- } else {
- expireAt = Math.max(request.getExpireIn() + elapsedRealtime, 0);
- }
- request.setExpireAt(Math.min(request.getExpireAt(), expireAt));
- request.setExpireIn(Long.MAX_VALUE);
-
+ mExpirationRealtimeMs = request.getExpirationRealtimeMs(SystemClock.elapsedRealtime());
mProvider = provider;
mRealRequest = request;
mRequest = request;
@@ -2472,7 +2386,8 @@ public class LocationManagerService extends ILocationManager.Stub {
final int uid = Binder.getCallingUid();
final long identity = Binder.clearCallingIdentity();
try {
- if (mBlacklist.isBlacklisted(packageName)) {
+ if (mSettingsStore.isLocationPackageBlacklisted(UserHandle.getUserId(uid),
+ packageName)) {
if (D) {
Log.d(TAG, "not returning last loc for blacklisted app: "
+ packageName);
@@ -2513,10 +2428,7 @@ public class LocationManagerService extends ILocationManager.Stub {
String op = resolutionLevelToOpStr(allowedResolutionLevel);
long locationAgeMs = TimeUnit.NANOSECONDS.toMillis(
SystemClock.elapsedRealtime() - location.getElapsedRealtimeNanos());
- if ((locationAgeMs > Settings.Global.getLong(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
- DEFAULT_LAST_LOCATION_MAX_AGE_MS))
+ if (locationAgeMs > mSettingsStore.getMaxLastLocationAgeMs()
&& (mAppOps.unsafeCheckOp(op, uid, packageName)
== AppOpsManager.MODE_FOREGROUND)) {
return null;
@@ -2575,11 +2487,7 @@ public class LocationManagerService extends ILocationManager.Stub {
boolean foreground = LocationManagerServiceUtils.isImportanceForeground(
mActivityManager.getPackageImportance(packageName));
if (!foreground) {
- long backgroundThrottleIntervalMs = Settings.Global.getLong(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
- DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
- if (locationAgeMs < backgroundThrottleIntervalMs) {
+ if (locationAgeMs < mSettingsStore.getBackgroundThrottleIntervalMs()) {
// not allowed to request new locations, so we can't return anything
return false;
}
@@ -2910,11 +2818,7 @@ public class LocationManagerService extends ILocationManager.Stub {
long identity = Binder.clearCallingIdentity();
try {
- return Settings.Secure.getIntForUser(
- mContext.getContentResolver(),
- Settings.Secure.LOCATION_MODE,
- Settings.Secure.LOCATION_MODE_OFF,
- userId) != Settings.Secure.LOCATION_MODE_OFF;
+ return mSettingsStore.isLocationEnabled(userId);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2969,7 +2873,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
// Check whether the expiry date has passed
- return record.mRealRequest.getExpireAt() >= now;
+ return record.mExpirationRealtimeMs >= now;
}
@GuardedBy("mLock")
@@ -3050,7 +2954,8 @@ public class LocationManagerService extends ILocationManager.Stub {
continue;
}
- if (mBlacklist.isBlacklisted(receiver.mCallerIdentity.mPackageName)) {
+ if (mSettingsStore.isLocationPackageBlacklisted(receiverUserId,
+ receiver.mCallerIdentity.mPackageName)) {
if (D) {
Log.d(TAG, "skipping loc update for blacklisted app: " +
receiver.mCallerIdentity.mPackageName);
@@ -3100,7 +3005,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
// track expired records
- if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) {
+ if (r.mRealRequest.getNumUpdates() <= 0 || r.mExpirationRealtimeMs < now) {
// notify the client it can remove this listener
r.mReceiver.callRemovedLocked();
if (deadUpdateRecords == null) {
@@ -3392,33 +3297,11 @@ public class LocationManagerService extends ILocationManager.Stub {
ipw.decreaseIndent();
}
- if (mBlacklist != null) {
- mBlacklist.dump(ipw);
- }
-
if (mExtraLocationControllerPackage != null) {
ipw.println("Location Controller Extra Package: " + mExtraLocationControllerPackage
+ (mExtraLocationControllerPackageEnabled ? " [enabled]" : "[disabled]"));
}
- if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
- ipw.println("Throttling Whitelisted Packages:");
- ipw.increaseIndent();
- for (String packageName : mBackgroundThrottlePackageWhitelist) {
- ipw.println(packageName);
- }
- ipw.decreaseIndent();
- }
-
- if (!mIgnoreSettingsPackageWhitelist.isEmpty()) {
- ipw.println("Bypass Whitelisted Packages:");
- ipw.increaseIndent();
- for (String packageName : mIgnoreSettingsPackageWhitelist) {
- ipw.println(packageName);
- }
- ipw.decreaseIndent();
- }
-
if (mLocationFudger != null) {
ipw.println("Location Fudger:");
ipw.increaseIndent();
@@ -3426,6 +3309,8 @@ public class LocationManagerService extends ILocationManager.Stub {
ipw.decreaseIndent();
}
+ mSettingsStore.dump(fd, pw, args);
+
ipw.println("Location Providers:");
ipw.increaseIndent();
for (LocationProvider provider : mProviders) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d6ecdeac1654..a6d216fea7e2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7846,10 +7846,18 @@ public class ActivityManagerService extends IActivityManager.Stub
false /* mountExtStorageFull */, abiOverride);
}
- // TODO: Move to ProcessList?
@GuardedBy("this")
final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
boolean disableHiddenApiChecks, boolean mountExtStorageFull, String abiOverride) {
+ return addAppLocked(info, customProcess, isolated, disableHiddenApiChecks,
+ false /* disableTestApiChecks */, mountExtStorageFull, abiOverride);
+ }
+
+ // TODO: Move to ProcessList?
+ @GuardedBy("this")
+ final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
+ boolean disableHiddenApiChecks, boolean disableTestApiChecks,
+ boolean mountExtStorageFull, String abiOverride) {
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
@@ -7884,7 +7892,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mPersistentStartingProcesses.add(app);
mProcessList.startProcessLocked(app, new HostingRecord("added application",
customProcess != null ? customProcess : app.processName),
- disableHiddenApiChecks, mountExtStorageFull, abiOverride);
+ disableHiddenApiChecks, disableTestApiChecks, mountExtStorageFull, abiOverride);
}
return app;
@@ -16056,6 +16064,10 @@ public class ActivityManagerService extends IActivityManager.Stub
enforceCallingPermission(android.Manifest.permission.DISABLE_HIDDEN_API_CHECKS,
"disable hidden API checks");
}
+ // Allow instrumented processes access to test APIs.
+ // TODO(satayev): make this configurable via testing framework.
+ boolean disableTestApiChecks = true;
+
final boolean mountExtStorageFull = isCallerShell()
&& (flags & INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL) != 0;
@@ -16070,7 +16082,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
ProcessRecord app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks,
- mountExtStorageFull, abiOverride);
+ disableTestApiChecks, mountExtStorageFull, abiOverride);
app.setActiveInstrumentation(activeInstr);
activeInstr.mFinished = false;
activeInstr.mRunningProcesses.add(app);
diff --git a/services/core/java/com/android/server/am/PendingIntentController.java b/services/core/java/com/android/server/am/PendingIntentController.java
index d75591cc7432..df76713d58a6 100644
--- a/services/core/java/com/android/server/am/PendingIntentController.java
+++ b/services/core/java/com/android/server/am/PendingIntentController.java
@@ -43,6 +43,7 @@ import android.util.Slog;
import com.android.internal.os.IResultReceiver;
import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.AlarmManagerInternal;
import com.android.server.LocalServices;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.SafeActivityOptions;
@@ -293,6 +294,8 @@ public class PendingIntentController {
PendingIntentController::handlePendingIntentCancelled, this, callbacks);
mH.sendMessage(m);
}
+ final AlarmManagerInternal ami = LocalServices.getService(AlarmManagerInternal.class);
+ ami.remove(new PendingIntent(rec));
}
private void handlePendingIntentCancelled(RemoteCallbackList<IResultReceiver> callbacks) {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 8be31a6e07c2..2bb703545cad 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1413,15 +1413,11 @@ public final class ProcessList {
/**
* @return {@code true} if process start is successful, false otherwise.
- * @param app
- * @param hostingRecord
- * @param disableHiddenApiChecks
- * @param abiOverride
*/
@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
- boolean disableHiddenApiChecks, boolean mountExtStorageFull,
- String abiOverride) {
+ boolean disableHiddenApiChecks, boolean disableTestApiChecks,
+ boolean mountExtStorageFull, String abiOverride) {
if (app.pendingStart) {
return true;
}
@@ -1566,6 +1562,10 @@ public final class ProcessList {
throw new IllegalStateException("Invalid API policy: " + policy);
}
runtimeFlags |= policyBits;
+
+ if (disableTestApiChecks) {
+ runtimeFlags |= Zygote.DISABLE_TEST_API_ENFORCEMENT_POLICY;
+ }
}
String useAppImageCache = SystemProperties.get(
@@ -1847,7 +1847,8 @@ public final class ProcessList {
final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
String abiOverride) {
return startProcessLocked(app, hostingRecord,
- false /* disableHiddenApiChecks */, false /* mountExtStorageFull */, abiOverride);
+ false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,
+ false /* mountExtStorageFull */, abiOverride);
}
@GuardedBy("mService")
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 0ea913f340b0..436167635662 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -1903,6 +1903,7 @@ class UserController implements Handler.Callback {
}
// Optimization - if there is no pending user switch, return current id
+ // (no need to acquire lock because mTargetUserId and mCurrentUserId are volatile)
if (mTargetUserId == UserHandle.USER_NULL) {
return getUserInfo(mCurrentUserId);
}
@@ -1919,7 +1920,7 @@ class UserController implements Handler.Callback {
int getCurrentOrTargetUserId() {
synchronized (mLock) {
- return mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId;
+ return getCurrentOrTargetUserIdLU();
}
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 2e36a4305fad..7e9a17bb8dbc 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -47,8 +47,8 @@ import android.app.AppOpsManager;
import android.app.AppOpsManager.HistoricalOps;
import android.app.AppOpsManager.HistoricalOpsRequest;
import android.app.AppOpsManager.Mode;
-import android.app.AppOpsManager.OpFeatureEntry;
import android.app.AppOpsManager.OpEntry;
+import android.app.AppOpsManager.OpFeatureEntry;
import android.app.AppOpsManager.OpFlags;
import android.app.AppOpsManagerInternal;
import android.app.AppOpsManagerInternal.CheckOpsDelegate;
@@ -119,6 +119,12 @@ import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.LockGuard;
+import libcore.util.EmptyArray;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -138,12 +144,6 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
-import libcore.util.EmptyArray;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
public class AppOpsService extends IAppOpsService.Stub {
static final String TAG = "AppOps";
static final boolean DEBUG = false;
@@ -2356,7 +2356,6 @@ public class AppOpsService extends IAppOpsService.Stub {
public void noteAsyncOp(String callingPackageName, int uid, String packageName, int opCode,
String featureId, String message) {
Preconditions.checkNotNull(message);
- Preconditions.checkNotNull(packageName);
verifyAndGetIsPrivileged(uid, packageName);
verifyIncomingUid(uid);
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 67d358910de1..232bc08e5b5c 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -21,6 +21,7 @@ import static android.service.attention.AttentionService.ATTENTION_FAILURE_CANCE
import static android.service.attention.AttentionService.ATTENTION_FAILURE_UNKNOWN;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.attention.AttentionManagerInternal;
@@ -85,6 +86,10 @@ public class AttentionManagerService extends SystemService {
/** If the check attention called within that period - cached value will be returned. */
private static final long STALE_AFTER_MILLIS = 5_000;
+ /** The size of the buffer that stores recent attention check results. */
+ @VisibleForTesting
+ protected static final int ATTENTION_CACHE_BUFFER_SIZE = 5;
+
/** DeviceConfig flag name, if {@code true}, enables AttentionManagerService features. */
private static final String SERVICE_ENABLED = "service_enabled";
private static String sTestAttentionServicePackage;
@@ -192,7 +197,8 @@ public class AttentionManagerService extends SystemService {
userState.bindLocked();
// throttle frequent requests
- final AttentionCheckCache cache = userState.mAttentionCheckCache;
+ final AttentionCheckCache cache = userState.mAttentionCheckCacheBuffer == null ? null
+ : userState.mAttentionCheckCacheBuffer.getLast();
if (cache != null && now < cache.mLastComputed + STALE_AFTER_MILLIS) {
callbackInternal.onSuccess(cache.mResult, cache.mTimestamp);
return true;
@@ -236,9 +242,11 @@ public class AttentionManagerService extends SystemService {
}
synchronized (mLock) {
- userState.mAttentionCheckCache = new AttentionCheckCache(
- SystemClock.uptimeMillis(), result,
- timestamp);
+ if (userState.mAttentionCheckCacheBuffer == null) {
+ userState.mAttentionCheckCacheBuffer = new AttentionCheckCacheBuffer();
+ }
+ userState.mAttentionCheckCacheBuffer.add(
+ new AttentionCheckCache(SystemClock.uptimeMillis(), result, timestamp));
}
StatsLog.write(
StatsLog.ATTENTION_MANAGER_SERVICE_RESULT_REPORTED,
@@ -421,7 +429,41 @@ public class AttentionManagerService extends SystemService {
}
}
- private static final class AttentionCheckCache {
+ @VisibleForTesting
+ protected static final class AttentionCheckCacheBuffer {
+ private final AttentionCheckCache[] mQueue;
+ private int mStartIndex;
+ private int mSize;
+
+ AttentionCheckCacheBuffer() {
+ mQueue = new AttentionCheckCache[ATTENTION_CACHE_BUFFER_SIZE];
+ mStartIndex = 0;
+ mSize = 0;
+ }
+
+ public AttentionCheckCache getLast() {
+ int lastIdx = (mStartIndex + mSize - 1) % ATTENTION_CACHE_BUFFER_SIZE;
+ return mSize == 0 ? null : mQueue[lastIdx];
+ }
+
+ public void add(@NonNull AttentionCheckCache cache) {
+ int nextIndex = (mStartIndex + mSize) % ATTENTION_CACHE_BUFFER_SIZE;
+ mQueue[nextIndex] = cache;
+ if (mSize == ATTENTION_CACHE_BUFFER_SIZE) {
+ mStartIndex++;
+ } else {
+ mSize++;
+ }
+ }
+
+ public AttentionCheckCache get(int offset) {
+ return offset >= mSize ? null
+ : mQueue[(mStartIndex + offset) % ATTENTION_CACHE_BUFFER_SIZE];
+ }
+ }
+
+ @VisibleForTesting
+ protected static final class AttentionCheckCache {
private final long mLastComputed;
private final int mResult;
private final long mTimestamp;
@@ -463,7 +505,7 @@ public class AttentionManagerService extends SystemService {
@GuardedBy("mLock")
AttentionCheck mCurrentAttentionCheck;
@GuardedBy("mLock")
- AttentionCheckCache mAttentionCheckCache;
+ AttentionCheckCacheBuffer mAttentionCheckCacheBuffer;
@GuardedBy("mLock")
private boolean mBinding;
@@ -532,13 +574,14 @@ public class AttentionManagerService extends SystemService {
pw.println("is fulfilled:=" + mCurrentAttentionCheck.mIsFulfilled);
pw.decreaseIndent();
}
- pw.println("attention check cache:");
- if (mAttentionCheckCache != null) {
- pw.increaseIndent();
- pw.println("last computed=" + mAttentionCheckCache.mLastComputed);
- pw.println("timestamp=" + mAttentionCheckCache.mTimestamp);
- pw.println("result=" + mAttentionCheckCache.mResult);
- pw.decreaseIndent();
+ if (mAttentionCheckCacheBuffer != null) {
+ pw.println("attention check cache:");
+ for (int i = 0; i < mAttentionCheckCacheBuffer.mSize; i++) {
+ pw.increaseIndent();
+ pw.println("timestamp=" + mAttentionCheckCacheBuffer.get(i).mTimestamp);
+ pw.println("result=" + mAttentionCheckCacheBuffer.get(i).mResult);
+ pw.decreaseIndent();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index e285bfdcdf4c..6355af6e0b2d 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1583,12 +1583,13 @@ public class AudioService extends IAudioService.Stub
setMicrophoneMuteNoCallerCheck(currentUser);
}
- private int rescaleIndex(int index, int srcStream, int dstStream) {
- int srcRange =
- mStreamStates[srcStream].getMaxIndex() - mStreamStates[srcStream].getMinIndex();
- int dstRange =
- mStreamStates[dstStream].getMaxIndex() - mStreamStates[dstStream].getMinIndex();
+ private int getIndexRange(int streamType) {
+ return (mStreamStates[streamType].getMaxIndex() - mStreamStates[streamType].getMinIndex());
+ }
+ private int rescaleIndex(int index, int srcStream, int dstStream) {
+ int srcRange = getIndexRange(srcStream);
+ int dstRange = getIndexRange(dstStream);
if (srcRange == 0) {
Log.e(TAG, "rescaleIndex : index range should not be zero");
return mStreamStates[dstStream].getMinIndex();
@@ -1599,6 +1600,17 @@ public class AudioService extends IAudioService.Stub
/ srcRange;
}
+ private int rescaleStep(int step, int srcStream, int dstStream) {
+ int srcRange = getIndexRange(srcStream);
+ int dstRange = getIndexRange(dstStream);
+ if (srcRange == 0) {
+ Log.e(TAG, "rescaleStep : index range should not be zero");
+ return 0;
+ }
+
+ return ((step * dstRange + srcRange / 2) / srcRange);
+ }
+
///////////////////////////////////////////////////////////////////////////
// IPC methods
///////////////////////////////////////////////////////////////////////////
@@ -1775,7 +1787,7 @@ public class AudioService extends IAudioService.Stub
}
} else {
// convert one UI step (+/-1) into a number of internal units on the stream alias
- step = rescaleIndex(10, streamType, streamTypeAlias);
+ step = rescaleStep(10, streamType, streamTypeAlias);
}
// If either the client forces allowing ringer modes for this adjustment,
diff --git a/services/core/java/com/android/server/location/GeofenceManager.java b/services/core/java/com/android/server/location/GeofenceManager.java
index 17a21694e725..81c06d7125f9 100644
--- a/services/core/java/com/android/server/location/GeofenceManager.java
+++ b/services/core/java/com/android/server/location/GeofenceManager.java
@@ -18,12 +18,11 @@ package com.android.server.location;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.database.ContentObserver;
import android.location.Geofence;
import android.location.Location;
import android.location.LocationListener;
@@ -31,13 +30,14 @@ import android.location.LocationManager;
import android.location.LocationRequest;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
-import android.os.UserHandle;
-import android.provider.Settings;
+import android.util.Log;
import android.util.Slog;
+import com.android.server.FgThread;
import com.android.server.LocationManagerService;
import com.android.server.PendingIntentUtils;
@@ -48,7 +48,7 @@ import java.util.List;
public class GeofenceManager implements LocationListener, PendingIntent.OnFinished {
private static final String TAG = "GeofenceManager";
- private static final boolean D = LocationManagerService.D;
+ private static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
private static final int MSG_UPDATE_FENCES = 1;
@@ -64,10 +64,6 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
*/
private static final long MAX_AGE_NANOS = 5 * 60 * 1000000000L; // five minutes
- /**
- * The default value of most frequent update interval allowed.
- */
- private static final long DEFAULT_MIN_INTERVAL_MS = 30 * 60 * 1000; // 30 minutes
/**
* Least frequent update interval allowed.
@@ -75,11 +71,13 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
private static final long MAX_INTERVAL_MS = 2 * 60 * 60 * 1000; // two hours
private final Context mContext;
+ private final GeofenceHandler mHandler;
+
private final LocationManager mLocationManager;
private final AppOpsManager mAppOps;
private final PowerManager.WakeLock mWakeLock;
- private final GeofenceHandler mHandler;
- private final LocationBlacklist mBlacklist;
+
+ private final LocationSettingsStore mSettingsStore;
private final Object mLock = new Object();
@@ -113,43 +111,17 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
*/
private boolean mPendingUpdate;
- /**
- * The actual value of most frequent update interval allowed.
- */
- private long mEffectiveMinIntervalMs;
- private ContentResolver mResolver;
-
- public GeofenceManager(Context context, LocationBlacklist blacklist) {
+ public GeofenceManager(Context context, LocationSettingsStore settingsStore) {
mContext = context;
- mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
- mAppOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE);
- PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
- mHandler = new GeofenceHandler();
- mBlacklist = blacklist;
- mResolver = mContext.getContentResolver();
- updateMinInterval();
- mResolver.registerContentObserver(
- Settings.Global.getUriFor(
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- updateMinInterval();
- }
- }
- }, UserHandle.USER_ALL);
- }
+ mHandler = new GeofenceHandler(FgThread.getHandler().getLooper());
- /**
- * Updates the minimal location request frequency.
- */
- private void updateMinInterval() {
- mEffectiveMinIntervalMs = Settings.Global.getLong(mResolver,
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
- DEFAULT_MIN_INTERVAL_MS);
+ mLocationManager = mContext.getSystemService(LocationManager.class);
+ mAppOps = mContext.getSystemService(AppOpsManager.class);
+
+ mWakeLock = mContext.getSystemService(PowerManager.class).newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK, TAG);
+
+ mSettingsStore = settingsStore;
}
public void addFence(LocationRequest request, Geofence geofence, PendingIntent intent,
@@ -161,8 +133,8 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
}
GeofenceState state = new GeofenceState(geofence,
- request.getExpireAt(), allowedResolutionLevel, uid, packageName, featureId,
- listenerIdentifier, intent);
+ request.getExpirationRealtimeMs(SystemClock.elapsedRealtime()),
+ allowedResolutionLevel, uid, packageName, featureId, listenerIdentifier, intent);
synchronized (mLock) {
// first make sure it doesn't already exist
for (int i = mFences.size() - 1; i >= 0; i--) {
@@ -294,7 +266,8 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
double minFenceDistance = Double.MAX_VALUE;
boolean needUpdates = false;
for (GeofenceState state : mFences) {
- if (mBlacklist.isBlacklisted(state.mPackageName)) {
+ if (mSettingsStore.isLocationPackageBlacklisted(ActivityManager.getCurrentUser(),
+ state.mPackageName)) {
if (D) {
Slog.d(TAG, "skipping geofence processing for blacklisted app: "
+ state.mPackageName);
@@ -340,10 +313,11 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
// Compute a location update interval based on the distance to the nearest fence.
long intervalMs;
if (location != null && Double.compare(minFenceDistance, Double.MAX_VALUE) != 0) {
- intervalMs = (long)Math.min(MAX_INTERVAL_MS, Math.max(mEffectiveMinIntervalMs,
+ intervalMs = (long) Math.min(MAX_INTERVAL_MS, Math.max(
+ mSettingsStore.getBackgroundThrottleProximityAlertIntervalMs(),
minFenceDistance * 1000 / MAX_SPEED_M_S));
} else {
- intervalMs = mEffectiveMinIntervalMs;
+ intervalMs = mSettingsStore.getBackgroundThrottleProximityAlertIntervalMs();
}
if (!mReceivingLocationUpdates || mLocationUpdateInterval != intervalMs) {
mReceivingLocationUpdates = true;
@@ -436,13 +410,16 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
}
@Override
- public void onStatusChanged(String provider, int status, Bundle extras) { }
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ }
@Override
- public void onProviderEnabled(String provider) { }
+ public void onProviderEnabled(String provider) {
+ }
@Override
- public void onProviderDisabled(String provider) { }
+ public void onProviderDisabled(String provider) {
+ }
@Override
public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
@@ -457,17 +434,14 @@ public class GeofenceManager implements LocationListener, PendingIntent.OnFinish
}
private final class GeofenceHandler extends Handler {
- public GeofenceHandler() {
- super(true /*async*/);
+ private GeofenceHandler(Looper looper) {
+ super(looper);
}
@Override
public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_UPDATE_FENCES: {
- updateFences();
- break;
- }
+ if (msg.what == MSG_UPDATE_FENCES) {
+ updateFences();
}
}
}
diff --git a/services/core/java/com/android/server/location/LocationBlacklist.java b/services/core/java/com/android/server/location/LocationBlacklist.java
deleted file mode 100644
index 3f3f82871c0f..000000000000
--- a/services/core/java/com/android/server/location/LocationBlacklist.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2012 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.location;
-
-import android.content.Context;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.Log;
-import android.util.Slog;
-
-import com.android.server.LocationManagerService;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * Allows applications to be blacklisted from location updates at run-time.
- *
- * This is a silent blacklist. Applications can still call Location Manager
- * API's, but they just won't receive any locations.
- */
-public final class LocationBlacklist extends ContentObserver {
- private static final String TAG = "LocationBlacklist";
- private static final boolean D = LocationManagerService.D;
- private static final String BLACKLIST_CONFIG_NAME = "locationPackagePrefixBlacklist";
- private static final String WHITELIST_CONFIG_NAME = "locationPackagePrefixWhitelist";
-
- private final Context mContext;
- private final Object mLock = new Object();
-
- // all fields below synchronized on mLock
- private String[] mWhitelist = new String[0];
- private String[] mBlacklist = new String[0];
-
- private int mCurrentUserId = UserHandle.USER_SYSTEM;
-
- public LocationBlacklist(Context context, Handler handler) {
- super(handler);
- mContext = context;
- }
-
- public void init() {
- mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
- BLACKLIST_CONFIG_NAME), false, this, UserHandle.USER_ALL);
-// mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
-// WHITELIST_CONFIG_NAME), false, this, UserHandle.USER_ALL);
- reloadBlacklist();
- }
-
- private void reloadBlacklistLocked() {
- mWhitelist = getStringArrayLocked(WHITELIST_CONFIG_NAME);
- if (D) Slog.d(TAG, "whitelist: " + Arrays.toString(mWhitelist));
- mBlacklist = getStringArrayLocked(BLACKLIST_CONFIG_NAME);
- if (D) Slog.d(TAG, "blacklist: " + Arrays.toString(mBlacklist));
- }
-
- private void reloadBlacklist() {
- synchronized (mLock) {
- reloadBlacklistLocked();
- }
- }
-
- /**
- * Return true if in blacklist
- * (package name matches blacklist, and does not match whitelist)
- */
- public boolean isBlacklisted(String packageName) {
- synchronized (mLock) {
- for (String black : mBlacklist) {
- if (packageName.startsWith(black)) {
- if (inWhitelist(packageName)) {
- continue;
- } else {
- if (D) Log.d(TAG, "dropping location (blacklisted): "
- + packageName + " matches " + black);
- return true;
- }
- }
- }
- }
- return false;
- }
-
- /**
- * Return true if any of packages are in whitelist
- */
- private boolean inWhitelist(String pkg) {
- synchronized (mLock) {
- for (String white : mWhitelist) {
- if (pkg.startsWith(white)) return true;
- }
- }
- return false;
- }
-
- @Override
- public void onChange(boolean selfChange) {
- reloadBlacklist();
- }
-
- public void switchUser(int userId) {
- synchronized(mLock) {
- mCurrentUserId = userId;
- reloadBlacklistLocked();
- }
- }
-
- private String[] getStringArrayLocked(String key) {
- String flatString;
- synchronized(mLock) {
- flatString = Settings.Secure.getStringForUser(mContext.getContentResolver(), key,
- mCurrentUserId);
- }
- if (flatString == null) {
- return new String[0];
- }
- String[] splitStrings = flatString.split(",");
- ArrayList<String> result = new ArrayList<String>();
- for (String pkg : splitStrings) {
- pkg = pkg.trim();
- if (pkg.isEmpty()) {
- continue;
- }
- result.add(pkg);
- }
- return result.toArray(new String[result.size()]);
- }
-
- public void dump(PrintWriter pw) {
- pw.println("mWhitelist=" + Arrays.toString(mWhitelist) + " mBlacklist=" +
- Arrays.toString(mBlacklist));
- }
-}
diff --git a/services/core/java/com/android/server/location/LocationSettingsStore.java b/services/core/java/com/android/server/location/LocationSettingsStore.java
new file mode 100644
index 000000000000..a4b6d97e9471
--- /dev/null
+++ b/services/core/java/com/android/server/location/LocationSettingsStore.java
@@ -0,0 +1,461 @@
+/*
+ * 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.location;
+
+import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS;
+import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST;
+import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS;
+import static android.provider.Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST;
+import static android.provider.Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS;
+import static android.provider.Settings.Secure.LOCATION_MODE;
+import static android.provider.Settings.Secure.LOCATION_MODE_OFF;
+import static android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Provides accessors and listeners for all location related settings.
+ */
+public class LocationSettingsStore {
+
+ private static final String LOCATION_PACKAGE_BLACKLIST = "locationPackagePrefixBlacklist";
+ private static final String LOCATION_PACKAGE_WHITELIST = "locationPackagePrefixWhitelist";
+
+ private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
+ private static final long DEFAULT_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS =
+ 30 * 60 * 1000;
+ private static final long DEFAULT_MAX_LAST_LOCATION_AGE_MS = 20 * 60 * 1000;
+
+ private final Context mContext;
+
+ private final IntegerSecureSetting mLocationMode;
+ private final StringListCachedSecureSetting mLocationProvidersAllowed;
+ private final LongGlobalSetting mBackgroundThrottleIntervalMs;
+ private final StringListCachedSecureSetting mLocationPackageBlacklist;
+ private final StringListCachedSecureSetting mLocationPackageWhitelist;
+ private final StringListCachedGlobalSetting mBackgroundThrottlePackageWhitelist;
+ private final StringListCachedGlobalSetting mIgnoreSettingsPackageWhitelist;
+
+ public LocationSettingsStore(Context context, Handler handler) {
+ mContext = context;
+
+ mLocationMode = new IntegerSecureSetting(context, LOCATION_MODE, handler);
+ mLocationProvidersAllowed = new StringListCachedSecureSetting(context,
+ LOCATION_PROVIDERS_ALLOWED, handler);
+ mBackgroundThrottleIntervalMs = new LongGlobalSetting(context,
+ LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS, handler);
+ mLocationPackageBlacklist = new StringListCachedSecureSetting(context,
+ LOCATION_PACKAGE_BLACKLIST, handler);
+ mLocationPackageWhitelist = new StringListCachedSecureSetting(context,
+ LOCATION_PACKAGE_WHITELIST, handler);
+ mBackgroundThrottlePackageWhitelist = new StringListCachedGlobalSetting(context,
+ LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST, handler);
+ mIgnoreSettingsPackageWhitelist = new StringListCachedGlobalSetting(context,
+ LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST, handler);
+ }
+
+ /**
+ * Retrieve if location is enabled or not.
+ */
+ public boolean isLocationEnabled(int userId) {
+ return mLocationMode.getValueForUser(LOCATION_MODE_OFF, userId) != LOCATION_MODE_OFF;
+ }
+
+ /**
+ * Add a listener for changes to the location enabled setting.
+ */
+ public void addOnLocationEnabledChangedListener(Runnable listener) {
+ mLocationMode.addListener(listener);
+ }
+
+ /**
+ * Remove a listener for changes to the location enabled setting.
+ */
+ public void removeOnLocationEnabledChangedListener(Runnable listener) {
+ mLocationMode.addListener(listener);
+ }
+
+ /**
+ * Retrieve the currently allowed location providers.
+ */
+ public List<String> getLocationProvidersAllowed(int userId) {
+ return mLocationProvidersAllowed.getValueForUser(userId);
+ }
+
+ /**
+ * Add a listener for changes to the currently allowed location providers.
+ */
+ public void addOnLocationProvidersAllowedChangedListener(Runnable runnable) {
+ mLocationProvidersAllowed.addListener(runnable);
+ }
+
+ /**
+ * Remove a listener for changes to the currently allowed location providers.
+ */
+ public void removeOnLocationProvidersAllowedChangedListener(Runnable runnable) {
+ mLocationProvidersAllowed.removeListener(runnable);
+ }
+
+ /**
+ * Retrieve the background throttle interval.
+ */
+ public long getBackgroundThrottleIntervalMs() {
+ return mBackgroundThrottleIntervalMs.getValue(DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
+ }
+
+ /**
+ * Add a listener for changes to the background throttle interval.
+ */
+ public void addOnBackgroundThrottleIntervalChangedListener(Runnable listener) {
+ mBackgroundThrottleIntervalMs.addListener(listener);
+ }
+
+ /**
+ * Remove a listener for changes to the background throttle interval.
+ */
+ public void removeOnBackgroundThrottleIntervalChangedListener(Runnable listener) {
+ mBackgroundThrottleIntervalMs.removeListener(listener);
+ }
+
+ /**
+ * Check if the given package is blacklisted for location access.
+ */
+ public boolean isLocationPackageBlacklisted(int userId, String packageName) {
+ List<String> locationPackageBlacklist = mLocationPackageBlacklist.getValueForUser(userId);
+ if (locationPackageBlacklist.isEmpty()) {
+ return false;
+ }
+
+ List<String> locationPackageWhitelist = mLocationPackageWhitelist.getValueForUser(userId);
+ for (String locationWhitelistPackage : locationPackageWhitelist) {
+ if (packageName.startsWith(locationWhitelistPackage)) {
+ return false;
+ }
+ }
+
+ for (String locationBlacklistPackage : locationPackageBlacklist) {
+ if (packageName.startsWith(locationBlacklistPackage)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Retrieve the background throttle package whitelist.
+ */
+ public List<String> getBackgroundThrottlePackageWhitelist() {
+ return mBackgroundThrottlePackageWhitelist.getValue();
+ }
+
+ /**
+ * Add a listener for changes to the background throttle package whitelist.
+ */
+ public void addOnBackgroundThrottlePackageWhitelistChangedListener(Runnable listener) {
+ mBackgroundThrottlePackageWhitelist.addListener(listener);
+ }
+
+ /**
+ * Remove a listener for changes to the background throttle package whitelist.
+ */
+ public void removeOnBackgroundThrottlePackageWhitelistChangedListener(Runnable listener) {
+ mBackgroundThrottlePackageWhitelist.removeListener(listener);
+ }
+
+ /**
+ * Retrieve the ignore settings package whitelist.
+ */
+ public List<String> getIgnoreSettingsPackageWhitelist() {
+ return mIgnoreSettingsPackageWhitelist.getValue();
+ }
+
+ /**
+ * Add a listener for changes to the ignore settings package whitelist.
+ */
+ public void addOnIgnoreSettingsPackageWhitelistChangedListener(Runnable listener) {
+ mIgnoreSettingsPackageWhitelist.addListener(listener);
+ }
+
+ /**
+ * Remove a listener for changes to the ignore settings package whitelist.
+ */
+ public void removeOnIgnoreSettingsPackageWhitelistChangedListener(Runnable listener) {
+ mIgnoreSettingsPackageWhitelist.removeListener(listener);
+ }
+
+ /**
+ * Retrieve the background throttling proximity alert interval.
+ */
+ public long getBackgroundThrottleProximityAlertIntervalMs() {
+ return Settings.Global.getLong(mContext.getContentResolver(),
+ LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
+ DEFAULT_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS);
+ }
+
+ public long getMaxLastLocationAgeMs() {
+ return Settings.Global.getLong(
+ mContext.getContentResolver(),
+ LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
+ DEFAULT_MAX_LAST_LOCATION_AGE_MS);
+ }
+
+ /**
+ * Dump info for debugging.
+ */
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ int userId = ActivityManager.getCurrentUser();
+
+ ipw.println("--Location Settings--");
+ ipw.increaseIndent();
+
+ ipw.print("Location Enabled: ");
+ ipw.println(isLocationEnabled(userId));
+
+ ipw.print("Location Providers Allowed: ");
+ ipw.println(getLocationProvidersAllowed(userId));
+
+ List<String> locationPackageBlacklist = mLocationPackageBlacklist.getValueForUser(userId);
+ if (!locationPackageBlacklist.isEmpty()) {
+ ipw.println("Location Blacklisted Packages:");
+ ipw.increaseIndent();
+ for (String packageName : locationPackageBlacklist) {
+ ipw.println(packageName);
+ }
+ ipw.decreaseIndent();
+
+ List<String> locationPackageWhitelist = mLocationPackageWhitelist.getValueForUser(
+ userId);
+ if (!locationPackageWhitelist.isEmpty()) {
+ ipw.println("Location Whitelisted Packages:");
+ ipw.increaseIndent();
+ for (String packageName : locationPackageWhitelist) {
+ ipw.println(packageName);
+ }
+ ipw.decreaseIndent();
+ }
+ }
+
+ List<String> backgroundThrottlePackageWhitelist =
+ mBackgroundThrottlePackageWhitelist.getValue();
+ if (!backgroundThrottlePackageWhitelist.isEmpty()) {
+ ipw.println("Throttling Whitelisted Packages:");
+ ipw.increaseIndent();
+ for (String packageName : backgroundThrottlePackageWhitelist) {
+ ipw.println(packageName);
+ }
+ ipw.decreaseIndent();
+ }
+
+ List<String> ignoreSettingsPackageWhitelist = mIgnoreSettingsPackageWhitelist.getValue();
+ if (!ignoreSettingsPackageWhitelist.isEmpty()) {
+ ipw.println("Bypass Whitelisted Packages:");
+ ipw.increaseIndent();
+ for (String packageName : ignoreSettingsPackageWhitelist) {
+ ipw.println(packageName);
+ }
+ ipw.decreaseIndent();
+ }
+ }
+
+ private abstract static class ObservingSetting extends ContentObserver {
+
+ private final CopyOnWriteArrayList<Runnable> mListeners;
+
+ private ObservingSetting(Context context, String settingName, Handler handler) {
+ super(handler);
+ mListeners = new CopyOnWriteArrayList<>();
+
+ context.getContentResolver().registerContentObserver(
+ getUriFor(settingName), false, this, UserHandle.USER_ALL);
+ }
+
+ public void addListener(Runnable listener) {
+ mListeners.add(listener);
+ }
+
+ public void removeListener(Runnable listener) {
+ mListeners.remove(listener);
+ }
+
+ protected abstract Uri getUriFor(String settingName);
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ for (Runnable listener : mListeners) {
+ listener.run();
+ }
+ }
+ }
+
+ private static class IntegerSecureSetting extends ObservingSetting {
+
+ private final Context mContext;
+ private final String mSettingName;
+
+ private IntegerSecureSetting(Context context, String settingName, Handler handler) {
+ super(context, settingName, handler);
+ mContext = context;
+ mSettingName = settingName;
+ }
+
+ public int getValueForUser(int defaultValue, int userId) {
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(), mSettingName,
+ defaultValue, userId);
+ }
+
+ @Override
+ protected Uri getUriFor(String settingName) {
+ return Settings.Secure.getUriFor(settingName);
+ }
+ }
+
+ private static class StringListCachedSecureSetting extends ObservingSetting {
+
+ private final Context mContext;
+ private final String mSettingName;
+
+ private int mCachedUserId = UserHandle.USER_NULL;
+ private List<String> mCachedValue;
+
+ private StringListCachedSecureSetting(Context context, String settingName,
+ Handler handler) {
+ super(context, settingName, handler);
+ mContext = context;
+ mSettingName = settingName;
+ }
+
+ public synchronized List<String> getValueForUser(int userId) {
+ if (userId != mCachedUserId) {
+ String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+ mSettingName, userId);
+ if (TextUtils.isEmpty(setting)) {
+ mCachedValue = Collections.emptyList();
+ } else {
+ mCachedValue = Arrays.asList(setting.split(","));
+ }
+ mCachedUserId = userId;
+ }
+
+ return mCachedValue;
+ }
+
+ public synchronized void invalidateForUser(int userId) {
+ if (mCachedUserId == userId) {
+ mCachedUserId = UserHandle.USER_NULL;
+ mCachedValue = null;
+ }
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ invalidateForUser(userId);
+ super.onChange(selfChange, uri, userId);
+ }
+
+ @Override
+ protected Uri getUriFor(String settingName) {
+ return Settings.Secure.getUriFor(settingName);
+ }
+ }
+
+ private static class LongGlobalSetting extends ObservingSetting {
+
+ private final Context mContext;
+ private final String mSettingName;
+
+ private LongGlobalSetting(Context context, String settingName, Handler handler) {
+ super(context, settingName, handler);
+ mContext = context;
+ mSettingName = settingName;
+ }
+
+ public long getValue(long defaultValue) {
+ return Settings.Global.getLong(mContext.getContentResolver(), mSettingName,
+ defaultValue);
+ }
+
+ @Override
+ protected Uri getUriFor(String settingName) {
+ return Settings.Global.getUriFor(settingName);
+ }
+ }
+
+ private static class StringListCachedGlobalSetting extends ObservingSetting {
+
+ private final Context mContext;
+ private final String mSettingName;
+
+ private boolean mValid;
+ private List<String> mCachedValue;
+
+ private StringListCachedGlobalSetting(Context context, String settingName,
+ Handler handler) {
+ super(context, settingName, handler);
+ mContext = context;
+ mSettingName = settingName;
+ }
+
+ public synchronized List<String> getValue() {
+ if (!mValid) {
+ String setting = Settings.Global.getString(mContext.getContentResolver(),
+ mSettingName);
+ if (TextUtils.isEmpty(setting)) {
+ mCachedValue = Collections.emptyList();
+ } else {
+ mCachedValue = Arrays.asList(setting.split(","));
+ }
+ mValid = true;
+ }
+
+ return mCachedValue;
+ }
+
+ public synchronized void invalidate() {
+ mValid = false;
+ mCachedValue = null;
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ invalidate();
+ super.onChange(selfChange, uri, userId);
+ }
+
+ @Override
+ protected Uri getUriFor(String settingName) {
+ return Settings.Global.getUriFor(settingName);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 193e0afc529e..c25e206d9104 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -1316,7 +1316,6 @@ public class MediaSessionService extends SystemService implements Monitor {
* pressed.
*
* @param packageName The caller's package name, obtained by Context#getPackageName()
- * @param opPackageName The caller's op package name, obtained by Context#getOpPackageName()
* @param sessionToken token for the session that the controller is pointing to
* @param keyEvent media key event
* @see #dispatchVolumeKeyEvent
@@ -1330,15 +1329,15 @@ public class MediaSessionService extends SystemService implements Monitor {
try {
synchronized (mLock) {
MediaSessionRecord record = getMediaSessionRecordLocked(sessionToken);
- if (record == null) {
- Log.w(TAG, "Failed to find session to dispatch key event.");
- return false;
- }
- if (DEBUG) {
+ if (DEBUG_KEY_EVENT) {
Log.d(TAG, "dispatchMediaKeyEventToSessionAsSystemService, pkg="
+ packageName + ", pid=" + pid + ", uid=" + uid + ", sessionToken="
+ sessionToken + ", event=" + keyEvent + ", session=" + record);
}
+ if (record == null) {
+ Log.w(TAG, "Failed to find session to dispatch key event.");
+ return false;
+ }
return record.sendMediaButton(packageName, pid, uid, true /* asSystemService */,
keyEvent, 0, null);
}
@@ -1688,6 +1687,12 @@ public class MediaSessionService extends SystemService implements Monitor {
try {
synchronized (mLock) {
MediaSessionRecord record = getMediaSessionRecordLocked(sessionToken);
+ if (DEBUG_KEY_EVENT) {
+ Log.d(TAG, "dispatchVolumeKeyEventToSessionAsSystemService, pkg="
+ + packageName + ", opPkg=" + opPackageName + ", pid=" + pid
+ + ", uid=" + uid + ", sessionToken=" + sessionToken + ", event="
+ + keyEvent + ", session=" + record);
+ }
if (record == null) {
Log.w(TAG, "Failed to find session to dispatch key event, token="
+ sessionToken + ". Fallbacks to the default handling.");
@@ -1695,12 +1700,6 @@ public class MediaSessionService extends SystemService implements Monitor {
keyEvent, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
return;
}
- if (DEBUG) {
- Log.d(TAG, "dispatchVolumeKeyEventToSessionAsSystemService, pkg="
- + packageName + ", opPkg=" + opPackageName + ", pid=" + pid
- + ", uid=" + uid + ", sessionToken=" + sessionToken + ", event="
- + keyEvent + ", session=" + record);
- }
switch (keyEvent.getAction()) {
case KeyEvent.ACTION_DOWN: {
int direction = 0;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 5e764012f46d..5b39fb687d0d 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -8960,6 +8960,7 @@ public class NotificationManagerService extends SystemService {
@VisibleForTesting
void resetAssistantUserSet(int userId) {
+ checkCallerIsSystemOrShell();
mAssistants.setUserSet(userId, false);
handleSavePolicyFile();
}
@@ -8967,12 +8968,14 @@ public class NotificationManagerService extends SystemService {
@VisibleForTesting
@Nullable
ComponentName getApprovedAssistant(int userId) {
+ checkCallerIsSystemOrShell();
List<ComponentName> allowedComponents = mAssistants.getAllowedComponents(userId);
return CollectionUtils.firstOrNull(allowedComponents);
}
@VisibleForTesting
protected void simulatePackageSuspendBroadcast(boolean suspend, String pkg) {
+ checkCallerIsSystemOrShell();
// only use for testing: mimic receive broadcast that package is (un)suspended
// but does not actually (un)suspend the package
final Bundle extras = new Bundle();
@@ -8989,6 +8992,7 @@ public class NotificationManagerService extends SystemService {
@VisibleForTesting
protected void simulatePackageDistractionBroadcast(int flag, String[] pkgs) {
+ checkCallerIsSystemOrShell();
// only use for testing: mimic receive broadcast that package is (un)distracting
// but does not actually register that info with packagemanager
final Bundle extras = new Bundle();
diff --git a/services/core/java/com/android/server/notification/NotificationShellCmd.java b/services/core/java/com/android/server/notification/NotificationShellCmd.java
index 979015dd8563..50f16bca8c8d 100644
--- a/services/core/java/com/android/server/notification/NotificationShellCmd.java
+++ b/services/core/java/com/android/server/notification/NotificationShellCmd.java
@@ -32,11 +32,13 @@ import android.app.Person;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
+import android.media.IRingtonePlayer;
import android.net.Uri;
import android.os.Binder;
import android.os.Process;
@@ -56,6 +58,7 @@ import java.util.Collections;
* Implementation of `cmd notification` in NotificationManagerService.
*/
public class NotificationShellCmd extends ShellCommand {
+ private static final String TAG = "NotifShellCmd";
private static final String USAGE = "usage: cmd notification SUBCMD [args]\n\n"
+ "SUBCMDs:\n"
+ " allow_listener COMPONENT [user_id (current user if not specified)]\n"
@@ -98,18 +101,19 @@ public class NotificationShellCmd extends ShellCommand {
+ "an <intentspec> is (broadcast|service|activity) <args>\n"
+ " <args> are as described in `am start`";
- public static final int NOTIFICATION_ID = 1138;
- public static final String NOTIFICATION_PACKAGE = "android";
- public static final String CHANNEL_ID = "shellcmd";
+ public static final int NOTIFICATION_ID = 2020;
+ public static final String CHANNEL_ID = "shell_cmd";
public static final String CHANNEL_NAME = "Shell command";
public static final int CHANNEL_IMP = NotificationManager.IMPORTANCE_DEFAULT;
private final NotificationManagerService mDirectService;
private final INotificationManager mBinderService;
+ private final PackageManager mPm;
public NotificationShellCmd(NotificationManagerService service) {
mDirectService = service;
mBinderService = service.getBinderService();
+ mPm = mDirectService.getContext().getPackageManager();
}
@Override
@@ -117,6 +121,19 @@ public class NotificationShellCmd extends ShellCommand {
if (cmd == null) {
return handleDefaultCommands(cmd);
}
+ String callingPackage = null;
+ final int callingUid = Binder.getCallingUid();
+ long identity = Binder.clearCallingIdentity();
+ try {
+ String[] packages = mPm.getPackagesForUid(callingUid);
+ if (packages != null && packages.length > 0) {
+ callingPackage = packages[0];
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "failed to get caller pkg", e);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
final PrintWriter pw = getOutPrintWriter();
try {
switch (cmd.replace('-', '_')) {
@@ -139,8 +156,7 @@ public class NotificationShellCmd extends ShellCommand {
interruptionFilter = INTERRUPTION_FILTER_ALL;
}
final int filter = interruptionFilter;
- Binder.withCleanCallingIdentity(() -> mBinderService.setInterruptionFilter(
- mDirectService.getContext().getPackageName(), filter));
+ mBinderService.setInterruptionFilter(callingPackage, filter);
}
break;
case "allow_dnd": {
@@ -258,7 +274,7 @@ public class NotificationShellCmd extends ShellCommand {
}
case "post":
case "notify":
- doNotify(pw);
+ doNotify(pw, callingPackage, callingUid);
break;
default:
return handleDefaultCommands(cmd);
@@ -270,27 +286,14 @@ public class NotificationShellCmd extends ShellCommand {
return 0;
}
- void ensureChannel() throws RemoteException {
- final int uid = Process.myUid();
- final int userid = UserHandle.getCallingUserId();
- final long token = Binder.clearCallingIdentity();
- try {
- if (mBinderService.getNotificationChannelForPackage(NOTIFICATION_PACKAGE,
- uid, CHANNEL_ID, false) == null) {
- final NotificationChannel chan = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME,
- CHANNEL_IMP);
- Slog.v(NotificationManagerService.TAG,
- "creating shell channel for user " + userid + " uid " + uid + ": " + chan);
- mBinderService.createNotificationChannelsForPackage(NOTIFICATION_PACKAGE, uid,
- new ParceledListSlice<NotificationChannel>(
- Collections.singletonList(chan)));
- Slog.v(NotificationManagerService.TAG, "created channel: "
- + mBinderService.getNotificationChannelForPackage(NOTIFICATION_PACKAGE,
- uid, CHANNEL_ID, false));
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ void ensureChannel(String callingPackage, int callingUid) throws RemoteException {
+ final NotificationChannel channel =
+ new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, CHANNEL_IMP);
+ mBinderService.createNotificationChannels(callingPackage,
+ new ParceledListSlice<>(Collections.singletonList(channel)));
+ Slog.v(NotificationManagerService.TAG, "created channel: "
+ + mBinderService.getNotificationChannel(callingPackage,
+ UserHandle.getUserId(callingUid), callingPackage, CHANNEL_ID));
}
Icon parseIcon(Resources res, String encoded) throws IllegalArgumentException {
@@ -319,7 +322,8 @@ public class NotificationShellCmd extends ShellCommand {
return null;
}
- private int doNotify(PrintWriter pw) throws RemoteException, URISyntaxException {
+ private int doNotify(PrintWriter pw, String callingPackage, int callingUid)
+ throws RemoteException, URISyntaxException {
final Context context = mDirectService.getContext();
final Resources res = context.getResources();
final Notification.Builder builder = new Notification.Builder(context, CHANNEL_ID);
@@ -513,26 +517,18 @@ public class NotificationShellCmd extends ShellCommand {
builder.setSmallIcon(smallIcon);
}
- ensureChannel();
+ ensureChannel(callingPackage, callingUid);
final Notification n = builder.build();
pw.println("posting:\n " + n);
Slog.v("NotificationManager", "posting: " + n);
- final int userId = UserHandle.getCallingUserId();
- final long token = Binder.clearCallingIdentity();
- try {
- mBinderService.enqueueNotificationWithTag(
- NOTIFICATION_PACKAGE, NOTIFICATION_PACKAGE,
- tag, NOTIFICATION_ID,
- n, userId);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ mBinderService.enqueueNotificationWithTag(callingPackage, callingPackage, tag,
+ NOTIFICATION_ID, n, UserHandle.getUserId(callingUid));
if (verbose) {
NotificationRecord nr = mDirectService.findNotificationLocked(
- NOTIFICATION_PACKAGE, tag, NOTIFICATION_ID, userId);
+ callingPackage, tag, NOTIFICATION_ID, UserHandle.getUserId(callingUid));
for (int tries = 3; tries-- > 0; ) {
if (nr != null) break;
try {
@@ -541,7 +537,7 @@ public class NotificationShellCmd extends ShellCommand {
} catch (InterruptedException e) {
}
nr = mDirectService.findNotificationLocked(
- NOTIFICATION_PACKAGE, tag, NOTIFICATION_ID, userId);
+ callingPackage, tag, NOTIFICATION_ID, UserHandle.getUserId(callingUid));
}
if (nr == null) {
pw.println("warning: couldn't find notification after enqueueing");
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 082b08debe9f..887dbb3f7de8 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -138,6 +138,13 @@ public class PreferencesHelper implements RankingConfig {
private boolean mAreChannelsBypassingDnd;
private boolean mHideSilentStatusBarIcons = DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS;
+ private static final String BADGING_FORCED_TRUE = "force_badging_true_for_bug";
+
+ // STOPSHIP (b/142218092) this should be removed before ship
+ static boolean wasBadgingForcedTrue(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(), BADGING_FORCED_TRUE, 0) != 0;
+ }
+
public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
ZenModeHelper zenHelper) {
mContext = context;
@@ -145,6 +152,14 @@ public class PreferencesHelper implements RankingConfig {
mRankingHandler = rankingHandler;
mPm = pm;
+ // STOPSHIP (b/142218092) this should be removed before ship
+ if (!wasBadgingForcedTrue(context)) {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.NOTIFICATION_BADGING,
+ DEFAULT_SHOW_BADGE ? 1 : 0);
+ Settings.Secure.putInt(context.getContentResolver(), BADGING_FORCED_TRUE, 1);
+ }
+
updateBadgingEnabled();
updateBubblesEnabled();
syncChannelsBypassingDnd(mContext.getUserId());
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index dc0cd184c188..5195a521dd17 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -211,7 +211,7 @@ public class AppsFilter {
final Uri data = intent.getData();
if ("content".equalsIgnoreCase(intent.getScheme())
&& data != null
- && providerInfo.authority.equalsIgnoreCase(data.getAuthority())) {
+ && Objects.equals(providerInfo.authority, data.getAuthority())) {
return true;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 340720e2f1fb..15e76fb9971c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5694,11 +5694,9 @@ public class PackageManagerService extends IPackageManager.Stub
PackageSetting ps = it.next();
if (ps.getInstalled(userId)) {
res[i++] = ps.name;
- } else {
- res = ArrayUtils.removeElement(String.class, res, res[i]);
}
}
- return res;
+ return ArrayUtils.trimToSize(res, i);
} else if (obj instanceof PackageSetting) {
final PackageSetting ps = (PackageSetting) obj;
if (ps.getInstalled(userId)
@@ -22256,8 +22254,9 @@ public class PackageManagerService extends IPackageManager.Stub
continue;
}
final String packageName = ps.pkg.packageName;
- // Skip over if system app
- if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ // Skip over if system app or static shared library
+ if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0
+ || !TextUtils.isEmpty(ps.pkg.staticSharedLibName)) {
continue;
}
if (DEBUG_CLEAN_APKS) {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index ec64ee6d52de..b6934c9ce604 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -16,7 +16,6 @@
package com.android.server.statusbar;
-import android.graphics.Rect;
import android.os.Bundle;
import android.view.InsetsState.InternalInsetType;
import android.view.WindowInsetsController.Appearance;
@@ -79,9 +78,7 @@ public interface StatusBarManagerInternal {
void startAssist(Bundle args);
void onCameraLaunchGestureDetected(int source);
void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive);
- void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, int dockedStackVis,
- int mask, Rect fullscreenBounds, Rect dockedBounds, boolean isNavbarColorManagedByIme,
- String cause);
+ void setDisableFlags(int displayId, int flags, String cause);
void toggleSplitScreen();
void appTransitionFinished(int displayId);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index effeb80298b8..25c41f5cdd6b 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -25,7 +25,6 @@ import android.app.Notification;
import android.app.StatusBarManager;
import android.content.ComponentName;
import android.content.Context;
-import android.graphics.Rect;
import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
@@ -43,10 +42,11 @@ import android.os.UserHandle;
import android.service.notification.NotificationStats;
import android.text.TextUtils;
import android.util.ArrayMap;
-import android.util.Log;
+import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import android.view.InsetsState.InternalInsetType;
import android.view.WindowInsetsController.Appearance;
import com.android.internal.R;
@@ -263,12 +263,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
@Override
- public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenBounds, Rect dockedBounds,
- boolean isNavbarColorManagedByIme, String cause) {
- StatusBarManagerService.this.setSystemUiVisibility(displayId, vis, fullscreenStackVis,
- dockedStackVis, mask, fullscreenBounds, dockedBounds, isNavbarColorManagedByIme,
- cause);
+ public void setDisableFlags(int displayId, int flags, String cause) {
+ StatusBarManagerService.this.setDisableFlags(displayId, flags, cause);
}
@Override
@@ -473,7 +469,10 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
@Override
public void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
- // TODO (b/118118435): save the information to UiState
+ final UiState state = getUiState(displayId);
+ if (!state.appearanceEquals(appearance, appearanceRegions, navbarColorManagedByIme)) {
+ state.setAppearance(appearance, appearanceRegions, navbarColorManagedByIme);
+ }
if (mBar != null) {
try {
mBar.onSystemBarAppearanceChanged(displayId, appearance, appearanceRegions,
@@ -483,7 +482,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
@Override
- public void showTransient(int displayId, int[] types) {
+ public void showTransient(int displayId, @InternalInsetType int[] types) {
+ getUiState(displayId).showTransient(types);
if (mBar != null) {
try {
mBar.showTransient(displayId, types);
@@ -492,7 +492,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
@Override
- public void abortTransient(int displayId, int[] types) {
+ public void abortTransient(int displayId, @InternalInsetType int[] types) {
+ getUiState(displayId).clearTransient(types);
if (mBar != null) {
try {
mBar.abortTransient(displayId, types);
@@ -896,54 +897,20 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
}
- @Override
- public void setSystemUiVisibility(int displayId, int vis, int mask, String cause) {
- final UiState state = getUiState(displayId);
- setSystemUiVisibility(displayId, vis, 0, 0, mask,
- state.mFullscreenStackBounds, state.mDockedStackBounds,
- state.mNavbarColorManagedByIme, cause);
- }
-
- private void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenBounds, Rect dockedBounds,
- boolean isNavbarColorManagedByIme, String cause) {
+ private void setDisableFlags(int displayId, int flags, String cause) {
// also allows calls from window manager which is in this process.
enforceStatusBarService();
- if (SPEW) Slog.d(TAG, "setSystemUiVisibility(0x" + Integer.toHexString(vis) + ")");
-
- synchronized (mLock) {
- updateUiVisibilityLocked(displayId, vis, fullscreenStackVis, dockedStackVis, mask,
- fullscreenBounds, dockedBounds, isNavbarColorManagedByIme);
- disableLocked(
- displayId,
- mCurrentUserId,
- vis & StatusBarManager.DISABLE_MASK,
- mSysUiVisToken,
- cause, 1);
+ final int unknownFlags = flags & ~StatusBarManager.DISABLE_MASK;
+ if (unknownFlags != 0) {
+ Slog.e(TAG, "Unknown disable flags: 0x" + Integer.toHexString(unknownFlags),
+ new RuntimeException());
}
- }
- private void updateUiVisibilityLocked(final int displayId, final int vis,
- final int fullscreenStackVis, final int dockedStackVis, final int mask,
- final Rect fullscreenBounds, final Rect dockedBounds,
- final boolean isNavbarColorManagedByIme) {
- final UiState state = getUiState(displayId);
- if (!state.systemUiStateEquals(vis, fullscreenStackVis, dockedStackVis,
- fullscreenBounds, dockedBounds, isNavbarColorManagedByIme)) {
- state.setSystemUiState(vis, fullscreenStackVis, dockedStackVis, fullscreenBounds,
- dockedBounds, isNavbarColorManagedByIme);
- mHandler.post(() -> {
- if (mBar != null) {
- try {
- mBar.setSystemUiVisibility(displayId, vis, fullscreenStackVis,
- dockedStackVis, mask, fullscreenBounds, dockedBounds,
- isNavbarColorManagedByIme);
- } catch (RemoteException ex) {
- Log.w(TAG, "Can not get StatusBar!");
- }
- }
- });
+ if (SPEW) Slog.d(TAG, "setDisableFlags(0x" + Integer.toHexString(flags) + ")");
+
+ synchronized (mLock) {
+ disableLocked(displayId, mCurrentUserId, flags, mSysUiVisToken, cause, 1);
}
}
@@ -965,11 +932,10 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
private class UiState {
- private int mSystemUiVisibility = 0;
- private int mFullscreenStackSysUiVisibility = 0;
- private int mDockedStackSysUiVisibility = 0;
- private final Rect mFullscreenStackBounds = new Rect();
- private final Rect mDockedStackBounds = new Rect();
+ private @Appearance int mAppearance = 0;
+ private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0];
+ private ArraySet<Integer> mTransientBarTypes = new ArraySet<>();
+ private boolean mNavbarColorManagedByIme = false;
private boolean mFullscreen = false;
private boolean mImmersive = false;
private int mDisabled1 = 0;
@@ -978,53 +944,63 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
private int mImeBackDisposition = 0;
private boolean mShowImeSwitcher = false;
private IBinder mImeToken = null;
- private boolean mNavbarColorManagedByIme = false;
- private int getDisabled1() {
- return mDisabled1;
+ private void setAppearance(@Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
+ mAppearance = appearance;
+ mAppearanceRegions = appearanceRegions;
+ mNavbarColorManagedByIme = navbarColorManagedByIme;
}
- private int getDisabled2() {
- return mDisabled2;
+ private boolean appearanceEquals(@Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
+ if (mAppearance != appearance || mAppearanceRegions.length != appearanceRegions.length
+ || mNavbarColorManagedByIme != navbarColorManagedByIme) {
+ return false;
+ }
+ for (int i = appearanceRegions.length - 1; i >= 0; i--) {
+ if (!mAppearanceRegions[i].equals(appearanceRegions[i])) {
+ return false;
+ }
+ }
+ return true;
}
- private void setDisabled(int disabled1, int disabled2) {
- mDisabled1 = disabled1;
- mDisabled2 = disabled2;
+ private void showTransient(@InternalInsetType int[] types) {
+ for (int type : types) {
+ mTransientBarTypes.add(type);
+ }
+ }
+
+ private void clearTransient(@InternalInsetType int[] types) {
+ for (int type : types) {
+ mTransientBarTypes.remove(type);
+ }
}
private void setFullscreen(boolean isFullscreen) {
mFullscreen = isFullscreen;
}
- private void setImmersive(boolean immersive) {
- mImmersive = immersive;
+ private void setImmersive(boolean isImmersive) {
+ mImmersive = isImmersive;
}
- private boolean disableEquals(int disabled1, int disabled2) {
- return mDisabled1 == disabled1 && mDisabled2 == disabled2;
+ private int getDisabled1() {
+ return mDisabled1;
}
- private void setSystemUiState(final int vis, final int fullscreenStackVis,
- final int dockedStackVis, final Rect fullscreenBounds, final Rect dockedBounds,
- final boolean navbarColorManagedByIme) {
- mSystemUiVisibility = vis;
- mFullscreenStackSysUiVisibility = fullscreenStackVis;
- mDockedStackSysUiVisibility = dockedStackVis;
- mFullscreenStackBounds.set(fullscreenBounds);
- mDockedStackBounds.set(dockedBounds);
- mNavbarColorManagedByIme = navbarColorManagedByIme;
+ private int getDisabled2() {
+ return mDisabled2;
}
- private boolean systemUiStateEquals(final int vis, final int fullscreenStackVis,
- final int dockedStackVis, final Rect fullscreenBounds, final Rect dockedBounds,
- final boolean navbarColorManagedByIme) {
- return mSystemUiVisibility == vis
- && mFullscreenStackSysUiVisibility == fullscreenStackVis
- && mDockedStackSysUiVisibility == dockedStackVis
- && mFullscreenStackBounds.equals(fullscreenBounds)
- && mDockedStackBounds.equals(dockedBounds)
- && mNavbarColorManagedByIme == navbarColorManagedByIme;
+ private void setDisabled(int disabled1, int disabled2) {
+ mDisabled1 = disabled1;
+ mDisabled2 = disabled2;
+ }
+
+ private boolean disableEquals(int disabled1, int disabled2) {
+ return mDisabled1 == disabled1 && mDisabled2 == disabled2;
}
private void setImeWindowState(final int vis, final int backDisposition,
@@ -1084,13 +1060,16 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
// TODO(b/118592525): Currently, status bar only works on the default display.
// Make it aware of multi-display if needed.
final UiState state = mDisplayUiState.get(DEFAULT_DISPLAY);
+ final int[] transientBarTypes = new int[state.mTransientBarTypes.size()];
+ for (int i = 0; i < transientBarTypes.length; i++) {
+ transientBarTypes[i] = state.mTransientBarTypes.valueAt(i);
+ }
return new RegisterStatusBarResult(icons, gatherDisableActionsLocked(mCurrentUserId, 1),
- state.mSystemUiVisibility, state.mImeWindowVis,
+ state.mAppearance, state.mAppearanceRegions, state.mImeWindowVis,
state.mImeBackDisposition, state.mShowImeSwitcher,
- gatherDisableActionsLocked(mCurrentUserId, 2),
- state.mFullscreenStackSysUiVisibility, state.mDockedStackSysUiVisibility,
- state.mImeToken, state.mFullscreenStackBounds, state.mDockedStackBounds,
- state.mNavbarColorManagedByIme, state.mFullscreen, state.mImmersive);
+ gatherDisableActionsLocked(mCurrentUserId, 2), state.mImeToken,
+ state.mNavbarColorManagedByIme, state.mFullscreen, state.mImmersive,
+ transientBarTypes);
}
}
diff --git a/services/core/java/com/android/server/wallpaper/GLHelper.java b/services/core/java/com/android/server/wallpaper/GLHelper.java
new file mode 100644
index 000000000000..1d733f53f055
--- /dev/null
+++ b/services/core/java/com/android/server/wallpaper/GLHelper.java
@@ -0,0 +1,148 @@
+/*
+ * 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.wallpaper;
+
+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_HEIGHT;
+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_WIDTH;
+import static android.opengl.EGL14.eglChooseConfig;
+import static android.opengl.EGL14.eglCreateContext;
+import static android.opengl.EGL14.eglCreatePbufferSurface;
+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.eglTerminate;
+import static android.opengl.GLES20.GL_MAX_TEXTURE_SIZE;
+import static android.opengl.GLES20.glGetIntegerv;
+
+import android.opengl.EGLConfig;
+import android.opengl.EGLContext;
+import android.opengl.EGLDisplay;
+import android.opengl.EGLSurface;
+import android.opengl.GLUtils;
+import android.os.SystemProperties;
+import android.util.Log;
+
+class GLHelper {
+ private static final String TAG = GLHelper.class.getSimpleName();
+ private static final int sMaxTextureSize;
+
+ static {
+ int maxTextureSize = SystemProperties.getInt("sys.max_texture_size", 0);
+ sMaxTextureSize = maxTextureSize > 0 ? maxTextureSize : retrieveTextureSizeFromGL();
+ }
+
+ private static int retrieveTextureSizeFromGL() {
+ try {
+ String err;
+
+ // Before we can retrieve info from GL,
+ // we have to create EGLContext, EGLConfig and EGLDisplay first.
+ // We will fail at querying info from GL once one of above failed.
+ // When this happens, we will use defValue instead.
+ EGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (eglDisplay == null || eglDisplay == EGL_NO_DISPLAY) {
+ err = "eglGetDisplay failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ }
+
+ if (!eglInitialize(eglDisplay, null, 0 /* majorOffset */, null, 1 /* minorOffset */)) {
+ err = "eglInitialize failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ }
+
+ EGLConfig eglConfig = null;
+ int[] configsCount = new int[1];
+ EGLConfig[] configs = new EGLConfig[1];
+ int[] configSpec = new int[] {
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 0,
+ EGL_DEPTH_SIZE, 0,
+ EGL_STENCIL_SIZE, 0,
+ EGL_CONFIG_CAVEAT, EGL_NONE,
+ EGL_NONE
+ };
+
+ if (!eglChooseConfig(eglDisplay, configSpec, 0 /* attrib_listOffset */,
+ configs, 0 /* configOffset */, 1 /* config_size */,
+ configsCount, 0 /* num_configOffset */)) {
+ err = "eglChooseConfig failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ } else if (configsCount[0] > 0) {
+ eglConfig = configs[0];
+ }
+
+ if (eglConfig == null) {
+ throw new RuntimeException("eglConfig not initialized!");
+ }
+
+ int[] attr_list = new int[] {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+ EGLContext eglContext = eglCreateContext(
+ eglDisplay, eglConfig, EGL_NO_CONTEXT, attr_list, 0 /* offset */);
+
+ if (eglContext == null || eglContext == EGL_NO_CONTEXT) {
+ err = "eglCreateContext failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ }
+
+ // We create a push buffer temporarily for querying info from GL.
+ int[] attrs = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
+ EGLSurface eglSurface =
+ eglCreatePbufferSurface(eglDisplay, eglConfig, attrs, 0 /* offset */);
+ eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
+
+ // Now, we are ready to query the info from GL.
+ int[] maxSize = new int[1];
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxSize, 0 /* offset */);
+
+ // We have got the info we want, release all egl resources.
+ eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroySurface(eglDisplay, eglSurface);
+ eglDestroyContext(eglDisplay, eglContext);
+ eglTerminate(eglDisplay);
+ return maxSize[0];
+ } catch (RuntimeException e) {
+ Log.w(TAG, "Retrieve from GL failed", e);
+ return Integer.MAX_VALUE;
+ }
+ }
+
+ static int getMaxTextureSize() {
+ return sMaxTextureSize;
+ }
+}
+
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 3663f4696a27..3cc6428c792b 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -134,6 +134,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
private static final boolean DEBUG = false;
private static final boolean DEBUG_LIVE = true;
+ // This 100MB limitation is defined in RecordingCanvas.
+ private static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024;
+
public static class Lifecycle extends SystemService {
private IWallpaperManagerService mService;
@@ -572,7 +575,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
// Only generate crop for default display.
final DisplayData wpData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
- Rect cropHint = new Rect(wallpaper.cropHint);
+ final Rect cropHint = new Rect(wallpaper.cropHint);
+ final DisplayInfo displayInfo = new DisplayInfo();
+ mDisplayManager.getDisplay(DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
if (DEBUG) {
Slog.v(TAG, "Generating crop for new wallpaper(s): 0x"
@@ -618,12 +623,12 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
// scale if the crop height winds up not matching the recommended metrics
- needScale = (wpData.mHeight != cropHint.height());
+ needScale = wpData.mHeight != cropHint.height()
+ || cropHint.height() > GLHelper.getMaxTextureSize()
+ || cropHint.width() > GLHelper.getMaxTextureSize();
//make sure screen aspect ratio is preserved if width is scaled under screen size
if (needScale) {
- final DisplayInfo displayInfo = new DisplayInfo();
- mDisplayManager.getDisplay(DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
final float scaleByHeight = (float) wpData.mHeight / (float) cropHint.height();
final int newWidth = (int) (cropHint.width() * scaleByHeight);
if (newWidth < displayInfo.logicalWidth) {
@@ -644,14 +649,29 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
if (!needCrop && !needScale) {
// Simple case: the nominal crop fits what we want, so we take
// the whole thing and just copy the image file directly.
- if (DEBUG) {
- Slog.v(TAG, "Null crop of new wallpaper; copying");
+
+ // TODO: It is not accurate to estimate bitmap size without decoding it,
+ // may be we can try to remove this optimized way in the future,
+ // that means, we will always go into the 'else' block.
+
+ // This is just a quick estimation, may be smaller than it is.
+ long estimateSize = options.outWidth * options.outHeight * 4;
+
+ // A bitmap over than MAX_BITMAP_SIZE will make drawBitmap() fail.
+ // Please see: RecordingCanvas#throwIfCannotDraw.
+ if (estimateSize < MAX_BITMAP_SIZE) {
+ success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
}
- success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
+
if (!success) {
wallpaper.cropFile.delete();
// TODO: fall back to default wallpaper in this case
}
+
+ if (DEBUG) {
+ Slog.v(TAG, "Null crop of new wallpaper, estimate size="
+ + estimateSize + ", success=" + success);
+ }
} else {
// Fancy case: crop and scale. First, we decode and scale down if appropriate.
FileOutputStream f = null;
@@ -665,49 +685,78 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
// We calculate the largest power-of-two under the actual ratio rather than
// just let the decode take care of it because we also want to remap where the
// cropHint rectangle lies in the decoded [super]rect.
- final BitmapFactory.Options scaler;
final int actualScale = cropHint.height() / wpData.mHeight;
int scale = 1;
- while (2*scale < actualScale) {
+ while (2 * scale <= actualScale) {
scale *= 2;
}
- if (scale > 1) {
- scaler = new BitmapFactory.Options();
- scaler.inSampleSize = scale;
+ options.inSampleSize = scale;
+ options.inJustDecodeBounds = false;
+
+ final Rect estimateCrop = new Rect(cropHint);
+ estimateCrop.scale(1f / options.inSampleSize);
+ final float hRatio = (float) wpData.mHeight / estimateCrop.height();
+ final int destHeight = (int) (estimateCrop.height() * hRatio);
+ final int destWidth = (int) (estimateCrop.width() * hRatio);
+
+ // We estimated an invalid crop, try to adjust the cropHint to get a valid one.
+ if (destWidth > GLHelper.getMaxTextureSize()) {
+ int newHeight = (int) (wpData.mHeight / hRatio);
+ int newWidth = (int) (wpData.mWidth / hRatio);
+
if (DEBUG) {
- Slog.v(TAG, "Downsampling cropped rect with scale " + scale);
+ Slog.v(TAG, "Invalid crop dimensions, trying to adjust.");
}
- } else {
- scaler = null;
+
+ estimateCrop.set(cropHint);
+ estimateCrop.left += (cropHint.width() - newWidth) / 2;
+ estimateCrop.top += (cropHint.height() - newHeight) / 2;
+ estimateCrop.right = estimateCrop.left + newWidth;
+ estimateCrop.bottom = estimateCrop.top + newHeight;
+ cropHint.set(estimateCrop);
+ estimateCrop.scale(1f / options.inSampleSize);
+ }
+
+ // We've got the safe cropHint; now we want to scale it properly to
+ // the desired rectangle.
+ // That's a height-biased operation: make it fit the hinted height.
+ final int safeHeight = (int) (estimateCrop.height() * hRatio);
+ final int safeWidth = (int) (estimateCrop.width() * hRatio);
+
+ if (DEBUG) {
+ Slog.v(TAG, "Decode parameters:");
+ Slog.v(TAG, " cropHint=" + cropHint + ", estimateCrop=" + estimateCrop);
+ Slog.v(TAG, " down sampling=" + options.inSampleSize
+ + ", hRatio=" + hRatio);
+ Slog.v(TAG, " dest=" + destWidth + "x" + destHeight);
+ Slog.v(TAG, " safe=" + safeWidth + "x" + safeHeight);
+ Slog.v(TAG, " maxTextureSize=" + GLHelper.getMaxTextureSize());
}
- Bitmap cropped = decoder.decodeRegion(cropHint, scaler);
+
+ Bitmap cropped = decoder.decodeRegion(cropHint, options);
decoder.recycle();
if (cropped == null) {
Slog.e(TAG, "Could not decode new wallpaper");
} else {
- // We've got the extracted crop; now we want to scale it properly to
- // the desired rectangle. That's a height-biased operation: make it
- // fit the hinted height, and accept whatever width we end up with.
- cropHint.offsetTo(0, 0);
- cropHint.right /= scale; // adjust by downsampling factor
- cropHint.bottom /= scale;
- final float heightR =
- ((float) wpData.mHeight) / ((float) cropHint.height());
- if (DEBUG) {
- Slog.v(TAG, "scale " + heightR + ", extracting " + cropHint);
- }
- final int destWidth = (int)(cropHint.width() * heightR);
+ // We are safe to create final crop with safe dimensions now.
final Bitmap finalCrop = Bitmap.createScaledBitmap(cropped,
- destWidth, wpData.mHeight, true);
+ safeWidth, safeHeight, true);
if (DEBUG) {
Slog.v(TAG, "Final extract:");
Slog.v(TAG, " dims: w=" + wpData.mWidth
+ " h=" + wpData.mHeight);
- Slog.v(TAG, " out: w=" + finalCrop.getWidth()
+ Slog.v(TAG, " out: w=" + finalCrop.getWidth()
+ " h=" + finalCrop.getHeight());
}
+ // A bitmap over than MAX_BITMAP_SIZE will make drawBitmap() fail.
+ // Please see: RecordingCanvas#throwIfCannotDraw.
+ if (finalCrop.getByteCount() > MAX_BITMAP_SIZE) {
+ throw new RuntimeException(
+ "Too large bitmap, limit=" + MAX_BITMAP_SIZE);
+ }
+
f = new FileOutputStream(wallpaper.cropFile);
bos = new BufferedOutputStream(f, 32*1024);
finalCrop.compress(Bitmap.CompressFormat.JPEG, 100, bos);
@@ -1997,6 +2046,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
if (!isWallpaperSupported(callingPackage)) {
return;
}
+
+ // Make sure both width and height are not larger than max texture size.
+ width = Math.min(width, GLHelper.getMaxTextureSize());
+ height = Math.min(height, GLHelper.getMaxTextureSize());
+
synchronized (mLock) {
int userId = UserHandle.getCallingUserId();
WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 48a7b73a5fc1..12681133d9c4 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -41,7 +41,6 @@ import static com.android.server.am.ActivityDisplayProto.RESUMED_ACTIVITY;
import static com.android.server.am.ActivityDisplayProto.SINGLE_TASK_INSTANCE;
import static com.android.server.am.ActivityDisplayProto.STACKS;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
@@ -1523,7 +1522,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
final ActivityStack stack = getChildAt(i);
final ArrayList<TaskRecord> tasks = stack.getAllTasks();
for (int j = tasks.size() - 1; j >= 0; --j) {
- stack.removeTask(tasks.get(j), "removeAllTasks", REMOVE_TASK_MODE_DESTROYING);
+ stack.removeChild(tasks.get(j), "removeAllTasks");
}
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index ff2c67135e5c..c506e274ef64 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -189,6 +189,8 @@ class ActivityMetricsLogger {
private int reason = APP_TRANSITION_TIMEOUT;
// TODO(b/132736359) The number may need to consider the visibility change.
private int numUndrawnActivities = 1;
+ /** Non-null if the application has reported drawn but its window hasn't. */
+ private Runnable pendingFullyDrawn;
private boolean loggedStartingWindowDrawn;
private boolean launchTraceActive;
@@ -716,6 +718,9 @@ class ActivityMetricsLogger {
BackgroundThread.getHandler().post(() -> logAppTransition(
currentTransitionDeviceUptime, currentTransitionDelayMs, infoSnapshot));
BackgroundThread.getHandler().post(() -> logAppDisplayed(infoSnapshot));
+ if (info.pendingFullyDrawn != null) {
+ info.pendingFullyDrawn.run();
+ }
info.launchedActivity.info.launchToken = null;
}
@@ -839,6 +844,15 @@ class ActivityMetricsLogger {
if (info == null) {
return null;
}
+ if (info.numUndrawnActivities > 0 && info.pendingFullyDrawn == null) {
+ // There are still undrawn activities, postpone reporting fully drawn until all of its
+ // windows are drawn. So that is closer to an usable state.
+ info.pendingFullyDrawn = () -> {
+ logAppTransitionReportedDrawn(r, restoredFromBundle);
+ info.pendingFullyDrawn = null;
+ };
+ return null;
+ }
// Record the handling of the reportFullyDrawn callback in the trace system. This is not
// actually used to trace this function, but instead the logical task that this function
@@ -849,9 +863,10 @@ class ActivityMetricsLogger {
final LogMaker builder = new LogMaker(APP_TRANSITION_REPORTED_DRAWN);
builder.setPackageName(r.packageName);
builder.addTaggedData(FIELD_CLASS_NAME, r.info.name);
- long currentTimestampNs = SystemClock.elapsedRealtimeNanos();
- long startupTimeMs =
- TimeUnit.NANOSECONDS.toMillis(currentTimestampNs - mLastTransitionStartTimeNs);
+ final long currentTimestampNs = SystemClock.elapsedRealtimeNanos();
+ final long startupTimeMs = info.pendingFullyDrawn != null
+ ? info.windowsDrawnDelayMs
+ : TimeUnit.NANOSECONDS.toMillis(currentTimestampNs - mLastTransitionStartTimeNs);
builder.addTaggedData(APP_TRANSITION_REPORTED_DRAWN_MS, startupTimeMs);
builder.setType(restoredFromBundle
? TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index db219fd4c5b5..8aa5e77a01b1 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1148,56 +1148,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
}
- // TODO(task-unify): Remove once TaskRecord and Task are unified.
TaskRecord getTaskRecord() {
return task;
}
/**
- * Sets reference to the {@link TaskRecord} the {@link ActivityRecord} will treat as its parent.
- * Note that this does not actually add the {@link ActivityRecord} as a {@link TaskRecord}
- * children. However, this method will clean up references to this {@link ActivityRecord} in
- * {@link ActivityStack}.
- * @param task The new parent {@link TaskRecord}.
- */
- // TODO(task-unify): Can be remove after task level unification. Callers can just use addChild
- void setTask(TaskRecord task) {
- // Do nothing if the {@link TaskRecord} is the same as the current {@link getTaskRecord}.
- if (task != null && task == getTaskRecord()) {
- return;
- }
-
- final ActivityStack oldStack = getActivityStack();
- final ActivityStack newStack = task != null ? task.getStack() : null;
-
- // Inform old stack (if present) of activity removal and new stack (if set) of activity
- // addition.
- if (oldStack != newStack) {
- if (oldStack != null) {
- oldStack.onActivityRemovedFromStack(this);
- }
-
- if (newStack != null) {
- newStack.onActivityAddedToStack(this);
- }
- }
-
- final TaskRecord oldTask = this.task;
- this.task = task;
-
- // This is attaching the activity to the task which we only want to do once.
- // TODO(task-unify): Need to re-work after unifying the task level since it will already
- // have a parent then. Just need to restructure the re-parent case not to do this. NOTE that
- // the reparenting flag passed in can't be used directly for this as it isn't set in
- // ActivityRecord#reparent() case that ends up calling this method.
- if (task != null && getParent() == null) {
- task.addChild(this);
- } else {
- onParentChanged(task, oldTask);
- }
- }
-
- /**
* Sets the Task on this activity for the purposes of re-use during launch where we will
* re-use another activity instead of this one for the launch.
*/
@@ -1212,7 +1167,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
TaskStack getStack() {
final Task task = getTask();
if (task != null) {
- return task.mStack;
+ return task.getTaskStack();
} else {
return null;
}
@@ -1220,8 +1175,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Override
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- final TaskRecord oldTask = (oldParent != null) ? ((Task) oldParent).mTaskRecord : null;
- final TaskRecord newTask = (newParent != null) ? ((Task) newParent).mTaskRecord : null;
+ final TaskRecord oldTask = oldParent != null ? (TaskRecord) oldParent : null;
+ final TaskRecord newTask = newParent != null ? (TaskRecord) newParent : null;
this.task = newTask;
super.onParentChanged(newParent, oldParent);
@@ -1230,14 +1185,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (oldParent == null && newParent != null) {
// First time we are adding the activity to the system.
- // TODO(task-unify): See if mVoiceInteraction variable is really needed after task level
- // unification.
- mVoiceInteraction = task.mTaskRecord != null && task.mTaskRecord.voiceSession != null;
+ mVoiceInteraction = newTask.voiceSession != null;
mInputDispatchingTimeoutNanos = getInputDispatchingTimeoutLocked(this) * 1000000L;
onDisplayChanged(task.getDisplayContent());
- if (task.mTaskRecord != null) {
- task.mTaskRecord.updateOverrideConfigurationFromLaunchBounds();
- }
+ // TODO(b/36505427): Maybe this call should be moved inside
+ // updateOverrideConfiguration()
+ newTask.updateOverrideConfigurationFromLaunchBounds();
// Make sure override configuration is up-to-date before using to create window
// controller.
updateSizeCompatMode();
@@ -1257,8 +1210,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (getDisplayContent() != null) {
getDisplayContent().mClosingApps.remove(this);
}
- } else if (mLastParent != null && mLastParent.mStack != null) {
- task.mStack.mExitingActivities.remove(this);
+ } else if (mLastParent != null && mLastParent.getTaskStack() != null) {
+ task.getTaskStack().mExitingActivities.remove(this);
}
final TaskStack stack = getStack();
@@ -1279,8 +1232,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Inform old stack (if present) of activity removal and new stack (if set) of activity
// addition.
if (oldStack != newStack) {
- // TODO(task-unify): Might be better to use onChildAdded and onChildRemoved signal for
- // this once task level is unified.
if (oldStack != null) {
oldStack.onActivityRemovedFromStack(this);
}
@@ -1964,15 +1915,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reparent: moving activity=%s"
+ " to task=%d at %d", this, task.mTaskId, position);
-
- reparent(newTask.getTask(), position);
- }
-
- // TODO(task-unify): Remove once Task level is unified.
- void onParentChanged(TaskRecord newParent, TaskRecord oldParent) {
- onParentChanged(
- newParent != null ? newParent.mTask : null,
- oldParent != null ? oldParent.mTask : null);
+ reparent(newTask, position);
}
private boolean isHomeIntent(Intent intent) {
@@ -2051,7 +1994,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
/**
* @return Stack value from current task, null if there is no task.
*/
- // TODO: Remove once ActivityStack and TaskStack are unified.
+ // TODO(stack-unify): Remove once ActivityStack and TaskStack are unified.
<T extends ActivityStack> T getActivityStack() {
return task != null ? (T) task.getStack() : null;
}
@@ -2339,7 +2282,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
/** Finish all activities in the task with the same affinity as this one. */
void finishActivityAffinity() {
- final ArrayList<ActivityRecord> activities = getTaskRecord().mActivities;
+ final ArrayList<ActivityRecord> activities = getTaskRecord().mChildren;
for (int index = activities.indexOf(this); index >= 0; --index) {
final ActivityRecord cur = activities.get(index);
if (!Objects.equals(cur.taskAffinity, taskAffinity)) {
@@ -2451,7 +2394,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
mUserId, System.identityHashCode(this),
task.mTaskId, shortComponentName, reason);
- final ArrayList<ActivityRecord> activities = task.mActivities;
+ final ArrayList<ActivityRecord> activities = task.mChildren;
final int index = activities.indexOf(this);
if (index < (task.getChildCount() - 1)) {
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
@@ -2505,7 +2448,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// When finishing the activity preemptively take the snapshot before the app window
// is marked as hidden and any configuration changes take place
if (mAtmService.mWindowManager.mTaskSnapshotController != null) {
- final ArraySet<Task> tasks = Sets.newArraySet(task.mTask);
+ final ArraySet<Task> tasks = Sets.newArraySet(task);
mAtmService.mWindowManager.mTaskSnapshotController.snapshotTasks(tasks);
mAtmService.mWindowManager.mTaskSnapshotController
.addSkipClosingAppSnapshotTasks(tasks);
@@ -2547,7 +2490,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// In this case, we can set the visibility of all the task overlay activities when
// we detect the last one is finishing to keep them in sync.
if (task.onlyHasTaskOverlayActivities(true /* excludeFinishing */)) {
- for (ActivityRecord taskOverlay : task.mActivities) {
+ for (int i = task.getChildCount() - 1; i >= 0 ; --i) {
+ final ActivityRecord taskOverlay = task.getChildAt(i);
if (!taskOverlay.mTaskOverlay) {
continue;
}
@@ -2819,8 +2763,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
/** Note: call {@link #cleanUp(boolean, boolean)} before this method. */
- // TODO(task-unify): Look into consolidating this with TaskRecord.removeChild once we unify
- // task level.
void removeFromHistory(String reason) {
finishActivityResults(Activity.RESULT_CANCELED, null /* resultData */);
makeFinishingLocked();
@@ -4668,7 +4610,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
// Check if position in task allows to become paused
- final int positionInTask = task.mActivities.indexOf(this);
+ final int positionInTask = task.mChildren.indexOf(this);
if (positionInTask == -1) {
throw new IllegalStateException("Activity not found in its task");
}
@@ -5396,7 +5338,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return INVALID_TASK_ID;
}
final TaskRecord task = r.task;
- final int activityNdx = task.mActivities.indexOf(r);
+ final int activityNdx = task.mChildren.indexOf(r);
if (activityNdx < 0
|| (onlyRoot && activityNdx > task.findRootIndex(true /* effectiveRoot */))) {
return INVALID_TASK_ID;
@@ -5760,7 +5702,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Override
boolean isWaitingForTransitionStart() {
final DisplayContent dc = getDisplayContent();
- // TODO: Test for null can be removed once unification is done.
+ // TODO(display-unify): Test for null can be removed once unification is done.
if (dc == null) return false;
return dc.mAppTransition.isTransitionSet()
&& (dc.mOpeningApps.contains(this)
@@ -5815,7 +5757,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mWmService.mTaskSnapshotController.createTaskSnapshot(
task, 1 /* scaleFraction */);
if (snapshot != null) {
- mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, t, this,
+ mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory, t, this,
snapshot.getGraphicBuffer(), true /* relative */);
}
}
@@ -5924,8 +5866,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return;
}
clearThumbnail();
- mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, getPendingTransaction(),
- this, thumbnailHeader);
+ mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory,
+ getPendingTransaction(), this, thumbnailHeader);
mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
}
@@ -5953,7 +5895,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (thumbnail == null) {
return;
}
- mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory,
+ mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory,
getPendingTransaction(), this, thumbnail);
final Animation animation =
getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
@@ -6101,7 +6043,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
@VisibleForTesting
- AppWindowThumbnail getThumbnail() {
+ WindowContainerThumbnail getThumbnail() {
return mThumbnail;
}
@@ -6568,8 +6510,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// If the changes come from change-listener, the incoming parent configuration is
// still the old one. Make sure their orientations are the same to reduce computing
// the compatibility bounds for the intermediate state.
- && (task.mTaskRecord == null || task.mTaskRecord
- .getConfiguration().orientation == newParentConfig.orientation)) {
+ && (task.getConfiguration().orientation == newParentConfig.orientation)) {
final Rect taskBounds = task.getBounds();
// Since we only center the activity horizontally, if only the fixed height is smaller
// than its container, the override bounds don't need to take effect.
@@ -6887,8 +6828,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
preserveWindow &= isResizeOnlyChange(changes);
final boolean hasResizeChange = hasResizeChange(changes & ~info.getRealConfigChanged());
if (hasResizeChange) {
- final boolean isDragResizing =
- getTaskRecord().getTask().isDragResizing();
+ final boolean isDragResizing = getTaskRecord().isDragResizing();
mRelaunchReason = isDragResizing ? RELAUNCH_REASON_FREE_RESIZE
: RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
} else {
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index edf8789b3688..7df1c15aedf4 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -254,7 +254,11 @@ class ActivityStack extends ConfigurationContainer {
@Override
protected void onParentChanged(
ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- ActivityDisplay display = getParent();
+ if (oldParent != null) {
+ mPrevDisplayId = ((ActivityDisplay) oldParent).mDisplayId;
+ }
+
+ final ActivityDisplay display = getParent();
if (display != null) {
// Rotations are relative to the display. This means if there are 2 displays rotated
// differently (eg. 2 monitors with one landscape and one portrait), moving a stack
@@ -292,18 +296,6 @@ class ActivityStack extends ConfigurationContainer {
RESTARTING_PROCESS
}
- @VisibleForTesting
- /* The various modes for the method {@link #removeTask}. */
- // Task is being completely removed from all stacks in the system.
- protected static final int REMOVE_TASK_MODE_DESTROYING = 0;
- // Task is being removed from this stack so we can add it to another stack. In the case we are
- // moving we don't want to perform some operations on the task like removing it from window
- // manager or recents.
- static final int REMOVE_TASK_MODE_MOVING = 1;
- // Similar to {@link #REMOVE_TASK_MODE_MOVING} and the task will be added to the top of its new
- // stack and the new stack will be on top of all stacks.
- static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2;
-
final ActivityTaskManagerService mService;
final WindowManagerService mWindowManager;
@@ -381,6 +373,8 @@ class ActivityStack extends ConfigurationContainer {
final int mStackId;
/** The attached Display's unique identifier, or -1 if detached */
int mDisplayId;
+ // Id of the previous display the stack was on.
+ int mPrevDisplayId = INVALID_DISPLAY;
/** Stores the override windowing-mode from before a transient mode change (eg. split) */
private int mRestoreOverrideWindowingMode = WINDOWING_MODE_UNDEFINED;
@@ -489,8 +483,8 @@ class ActivityStack extends ConfigurationContainer {
int numActivities() {
int count = 0;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- count += mTaskHistory.get(taskNdx).getChildCount();
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ count += getChildAt(taskNdx).getChildCount();
}
return count;
}
@@ -962,7 +956,7 @@ class ActivityStack extends ConfigurationContainer {
void positionChildWindowContainerAtTop(TaskRecord child) {
if (mTaskStack != null) {
// TODO: Remove after unification. This cannot be false after that.
- mTaskStack.positionChildAtTop(child.getTask(), true /* includingParents */);
+ mTaskStack.positionChildAtTop(child, true /* includingParents */);
}
}
@@ -974,7 +968,7 @@ class ActivityStack extends ConfigurationContainer {
child.getStack(), true /* ignoreCurrent */);
if (mTaskStack != null) {
// TODO: Remove after unification. This cannot be false after that.
- mTaskStack.positionChildAtBottom(child.getTask(),
+ mTaskStack.positionChildAtBottom(child,
nextFocusableStack == null /* includingParents */);
}
}
@@ -1062,14 +1056,14 @@ class ActivityStack extends ConfigurationContainer {
void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) {
outActivities.clear();
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- mTaskHistory.get(taskNdx).getAllRunningVisibleActivitiesLocked(outActivities);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ getChildAt(taskNdx).getAllRunningVisibleActivitiesLocked(outActivities);
}
}
ActivityRecord topRunningActivityLocked(boolean focusableOnly) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked();
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ ActivityRecord r = getChildAt(taskNdx).topRunningActivityLocked();
if (r != null && (!focusableOnly || r.isFocusable())) {
return r;
}
@@ -1078,8 +1072,8 @@ class ActivityStack extends ConfigurationContainer {
}
ActivityRecord topRunningNonOverlayTaskActivity() {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (!r.finishing && !r.mTaskOverlay) {
@@ -1091,8 +1085,8 @@ class ActivityStack extends ConfigurationContainer {
}
ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (!r.finishing && !r.delayedResume && r != notTop && r.okToShowLocked()) {
@@ -1113,8 +1107,8 @@ class ActivityStack extends ConfigurationContainer {
* @return Returns the HistoryRecord of the next activity on the stack.
*/
final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ TaskRecord task = getChildAt(taskNdx);
if (task.mTaskId == taskId) {
continue;
}
@@ -1130,8 +1124,8 @@ class ActivityStack extends ConfigurationContainer {
}
ActivityRecord getTopActivity() {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final ActivityRecord r = mTaskHistory.get(taskNdx).getTopActivity();
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final ActivityRecord r = getChildAt(taskNdx).getTopActivity();
if (r != null) {
return r;
}
@@ -1140,16 +1134,16 @@ class ActivityStack extends ConfigurationContainer {
}
final TaskRecord topTask() {
- final int size = mTaskHistory.size();
+ final int size = getChildCount();
if (size > 0) {
- return mTaskHistory.get(size - 1);
+ return getChildAt(size - 1);
}
return null;
}
TaskRecord taskForIdLocked(int id) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
if (task.mTaskId == id) {
return task;
}
@@ -1168,7 +1162,7 @@ class ActivityStack extends ConfigurationContainer {
}
final TaskRecord task = r.getTaskRecord();
final ActivityStack stack = r.getActivityStack();
- if (stack != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
+ if (stack != null && task.mChildren.contains(r) && mTaskHistory.contains(task)) {
if (stack != this) Slog.w(TAG,
"Illegal state! task does not point to stack it is in.");
return r;
@@ -1182,8 +1176,10 @@ class ActivityStack extends ConfigurationContainer {
/** Checks if there are tasks with specific UID in the stack. */
boolean isUidPresent(int uid) {
- for (TaskRecord task : mTaskHistory) {
- for (ActivityRecord r : task.mActivities) {
+ for (int j = getChildCount() - 1; j >= 0; --j) {
+ final TaskRecord task = getChildAt(j);
+ for (int i = task.getChildCount() - 1; i >= 0 ; --i) {
+ final ActivityRecord r = task.getChildAt(i);
if (r.getUid() == uid) {
return true;
}
@@ -1194,8 +1190,10 @@ class ActivityStack extends ConfigurationContainer {
/** Get all UIDs that are present in the stack. */
void getPresentUIDs(IntArray presentUIDs) {
- for (TaskRecord task : mTaskHistory) {
- for (ActivityRecord r : task.mActivities) {
+ for (int j = getChildCount() - 1; j >= 0; --j) {
+ final TaskRecord task = getChildAt(j);
+ for (int i = task.getChildCount() - 1; i >= 0 ; --i) {
+ final ActivityRecord r = task.getChildAt(i);
presentUIDs.add(r.getUid());
}
}
@@ -1207,12 +1205,6 @@ class ActivityStack extends ConfigurationContainer {
return display != null && display.isSingleTaskInstance();
}
- private void removeActivitiesFromLRUList(TaskRecord task) {
- for (ActivityRecord r : task.mActivities) {
- mLRUActivities.remove(r);
- }
- }
-
/** @return {@code true} if LRU list contained the specified activity. */
final boolean removeActivityFromLRUList(ActivityRecord activity) {
return mLRUActivities.remove(activity);
@@ -1234,8 +1226,8 @@ class ActivityStack extends ConfigurationContainer {
private boolean returnsToHomeStack() {
return !inMultiWindowMode()
- && !mTaskHistory.isEmpty()
- && mTaskHistory.get(0).returnsToHomeStack();
+ && hasChild()
+ && getChildAt(0).returnsToHomeStack();
}
void moveToFront(String reason) {
@@ -1338,8 +1330,8 @@ class ActivityStack extends ConfigurationContainer {
Uri documentData = isDocument ? intent.getData() : null;
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + this);
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
if (task.voiceSession != null) {
// We never match voice sessions; those always run independently.
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
@@ -1429,8 +1421,8 @@ class ActivityStack extends ConfigurationContainer {
}
final int userId = UserHandle.getUserId(info.applicationInfo.uid);
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (!r.okToShowLocked()) {
@@ -1463,9 +1455,9 @@ class ActivityStack extends ConfigurationContainer {
mCurrentUser = userId;
// Move userId's tasks to the top.
- int index = mTaskHistory.size();
+ int index = getChildCount();
for (int i = 0; i < index; ) {
- final TaskRecord task = mTaskHistory.get(i);
+ final TaskRecord task = getChildAt(i);
if (task.okToShowLocked()) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "switchUser: stack=" + getStackId() +
@@ -1497,8 +1489,8 @@ class ActivityStack extends ConfigurationContainer {
void awakeFromSleepingLocked() {
// Ensure activities are no longer sleeping.
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
r.setSleeping(false);
@@ -1514,8 +1506,8 @@ class ActivityStack extends ConfigurationContainer {
final String packageName = aInfo.packageName;
final int userId = UserHandle.getUserId(aInfo.uid);
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord ar = task.getChildAt(activityNdx);
@@ -1592,8 +1584,8 @@ class ActivityStack extends ConfigurationContainer {
// Make sure any paused or stopped but visible activities are now sleeping.
// This ensures that the activity's onStop() is called.
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (r.isState(STARTED, STOPPING, STOPPED, PAUSED, PAUSING)) {
@@ -1876,8 +1868,8 @@ class ActivityStack extends ConfigurationContainer {
if (!isAttached() || mForceHidden) {
return true;
}
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
@@ -2057,8 +2049,8 @@ class ActivityStack extends ConfigurationContainer {
final int rankTaskLayers(int baseLayer) {
int layer = 0;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
ActivityRecord r = task.topRunningActivityLocked();
if (r == null || r.finishing || !r.visible) {
task.mLayerRank = -1;
@@ -2108,8 +2100,8 @@ class ActivityStack extends ConfigurationContainer {
// to be visible (such as performing Recents animation).
final boolean resumeTopActivity = isFocusable() && isInStackLocked(starting) == null
&& top != null && !top.mLaunchTaskBehind;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
final boolean isTop = r == top;
@@ -2206,8 +2198,8 @@ class ActivityStack extends ConfigurationContainer {
}
void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- mTaskHistory.get(taskNdx).addStartingWindowsForVisibleActivities(taskSwitch);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ getChildAt(taskNdx).addStartingWindowsForVisibleActivities(taskSwitch);
}
}
@@ -2352,8 +2344,8 @@ class ActivityStack extends ConfigurationContainer {
}
void clearOtherAppTimeTrackers(AppTimeTracker except) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if ( r.appTimeTracker != except) {
@@ -2426,8 +2418,8 @@ class ActivityStack extends ConfigurationContainer {
}
final ActivityRecord topActivity = topRunningActivityLocked();
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (aboveTop) {
@@ -2979,7 +2971,7 @@ class ActivityStack extends ConfigurationContainer {
int getAdjustedPositionForTask(TaskRecord task, int suggestedPosition,
ActivityRecord starting) {
- int maxPosition = mTaskHistory.size();
+ int maxPosition = getChildCount();
if ((starting != null && starting.okToShowLocked())
|| (starting == null && task.okToShowLocked())) {
// If the task or starting activity can be shown, then whatever position is okay.
@@ -2988,7 +2980,7 @@ class ActivityStack extends ConfigurationContainer {
// The task can't be shown, put non-current user tasks below current user tasks.
while (maxPosition > 0) {
- final TaskRecord tmpTask = mTaskHistory.get(maxPosition - 1);
+ final TaskRecord tmpTask = getChildAt(maxPosition - 1);
if (!mStackSupervisor.isCurrentProfileLocked(tmpTask.mUserId)
|| tmpTask.topRunningActivityLocked() == null) {
break;
@@ -3004,7 +2996,7 @@ class ActivityStack extends ConfigurationContainer {
* @see ActivityTaskManagerService#positionTaskInStack(int, int, int).
*/
private void insertTaskAtPosition(TaskRecord task, int position) {
- if (position >= mTaskHistory.size()) {
+ if (position >= getChildCount()) {
insertTaskAtTop(task, null);
return;
} else if (position <= 0) {
@@ -3015,19 +3007,19 @@ class ActivityStack extends ConfigurationContainer {
mTaskHistory.remove(task);
mTaskHistory.add(position, task);
if (mTaskStack != null) {
- // TODO: this could not be false after unification.
- mTaskStack.positionChildAt(task.getTask(), position);
+ // TODO: this can not be false after unification Stack.
+ mTaskStack.positionChildAt(task, position);
}
- updateTaskMovement(task, true);
+ task.updateTaskMovement(true);
}
- private void insertTaskAtTop(TaskRecord task, ActivityRecord starting) {
- // TODO: Better place to put all the code below...may be addTask...
+ void insertTaskAtTop(TaskRecord task, ActivityRecord starting) {
+ // TODO: Better place to put all the code below...may be addChild...
mTaskHistory.remove(task);
// Now put task at top.
- final int position = getAdjustedPositionForTask(task, mTaskHistory.size(), starting);
+ final int position = getAdjustedPositionForTask(task, getChildCount(), starting);
mTaskHistory.add(position, task);
- updateTaskMovement(task, true);
+ task.updateTaskMovement(true);
positionChildWindowContainerAtTop(task);
}
@@ -3035,7 +3027,7 @@ class ActivityStack extends ConfigurationContainer {
mTaskHistory.remove(task);
final int position = getAdjustedPositionForTask(task, 0, null);
mTaskHistory.add(position, task);
- updateTaskMovement(task, true);
+ task.updateTaskMovement(true);
positionChildWindowContainerAtBottom(task);
}
@@ -3056,8 +3048,8 @@ class ActivityStack extends ConfigurationContainer {
if (!newTask) {
// If starting in an existing task, find where that is...
boolean startIt = true;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ task = getChildAt(taskNdx);
if (task.getTopActivity() == null) {
// All activities in task are finishing.
continue;
@@ -3069,7 +3061,7 @@ class ActivityStack extends ConfigurationContainer {
if (!startIt) {
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
+ task, new RuntimeException("here").fillInStackTrace());
- r.setTask(rTask);
+ rTask.positionChildAtTop(r);
ActivityOptions.abort(options);
return;
}
@@ -3085,7 +3077,7 @@ class ActivityStack extends ConfigurationContainer {
// If we are not placing the new activity frontmost, we do not want to deliver the
// onUserLeaving callback to the actual frontmost activity
final TaskRecord activityTask = r.getTaskRecord();
- if (task == activityTask && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
+ if (task == activityTask && mTaskHistory.indexOf(task) != (getChildCount() - 1)) {
mStackSupervisor.mUserLeaving = false;
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
"startActivity() behind front, mUserLeaving=false");
@@ -3096,7 +3088,7 @@ class ActivityStack extends ConfigurationContainer {
// Slot the activity into the history stack and proceed
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
new RuntimeException("here").fillInStackTrace());
- r.setTask(task);
+ task.positionChildAtTop(r);
// The transition animation and starting window are not needed if {@code allowMoveToFront}
// is false, because the activity won't be visible.
@@ -3271,8 +3263,8 @@ class ActivityStack extends ConfigurationContainer {
// with the same affinity is unlikely to be in the same stack.
final TaskRecord targetTask;
final ActivityRecord bottom =
- !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
- mTaskHistory.get(0).getChildAt(0) : null;
+ hasChild() && getChildAt(0).hasChild() ?
+ getChildAt(0).getChildAt(0) : null;
if (bottom != null && target.taskAffinity.equals(bottom.getTaskRecord().affinity)) {
// If the activity currently at the bottom has the
// same task affinity as the one we are moving,
@@ -3374,7 +3366,7 @@ class ActivityStack extends ConfigurationContainer {
if (singleTaskInstanceDisplay || display.alwaysCreateStack(getWindowingMode(),
getActivityType())) {
for (int index = numTasksCreated - 1; index >= 0; index--) {
- final TaskRecord targetTask = mTaskHistory.get(index);
+ final TaskRecord targetTask = getChildAt(index);
final ActivityStack targetStack = display.getOrCreateStack(getWindowingMode(),
getActivityType(), false /* onTop */);
targetTask.reparent(targetStack, false /* toTop */,
@@ -3482,7 +3474,7 @@ class ActivityStack extends ConfigurationContainer {
// instance of the same activity? Then we drop the instance
// below so it remains singleTop.
if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
- final ArrayList<ActivityRecord> taskActivities = task.mActivities;
+ final ArrayList<ActivityRecord> taskActivities = task.mChildren;
final int targetNdx = taskActivities.indexOf(target);
if (targetNdx > 0) {
final ActivityRecord p = taskActivities.get(targetNdx - 1);
@@ -3525,8 +3517,8 @@ class ActivityStack extends ConfigurationContainer {
// Preserve the location for reparenting in the new task.
int reparentInsertionPoint = -1;
- for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
- final TaskRecord targetTask = mTaskHistory.get(i);
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final TaskRecord targetTask = getChildAt(i);
if (targetTask == task) {
topOptions = resetTargetTaskIfNeededLocked(task, forceReset);
@@ -3539,7 +3531,7 @@ class ActivityStack extends ConfigurationContainer {
int taskNdx = mTaskHistory.indexOf(task);
if (taskNdx >= 0) {
- ActivityRecord newTop = mTaskHistory.get(taskNdx).getTopActivity();
+ ActivityRecord newTop = getChildAt(taskNdx).getTopActivity();
if (newTop != null) {
taskTop = newTop;
}
@@ -3602,8 +3594,8 @@ class ActivityStack extends ConfigurationContainer {
/** Finish all activities that were started for result from the specified activity. */
final void finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (r.resultTo == self && r.requestCode == requestCode) {
@@ -3636,7 +3628,7 @@ class ActivityStack extends ConfigurationContainer {
finishedTask = r.getTaskRecord();
int taskNdx = mTaskHistory.indexOf(finishedTask);
final TaskRecord task = finishedTask;
- int activityNdx = task.mActivities.indexOf(r);
+ int activityNdx = task.mChildren.indexOf(r);
getDisplay().mDisplayContent.prepareAppTransition(
TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
r.finishIfPossible(reason, false /* oomAdj */);
@@ -3651,11 +3643,11 @@ class ActivityStack extends ConfigurationContainer {
if (taskNdx < 0) {
break;
}
- activityNdx = mTaskHistory.get(taskNdx).getChildCount() - 1;
+ activityNdx = getChildAt(taskNdx).getChildCount() - 1;
} while (activityNdx < 0);
}
if (activityNdx >= 0) {
- r = mTaskHistory.get(taskNdx).getChildAt(activityNdx);
+ r = getChildAt(taskNdx).getChildAt(activityNdx);
if (r.isState(STARTED, RESUMED, PAUSING, PAUSED)) {
if (!r.isActivityTypeHome() || mService.mHomeProcess != r.app) {
Slog.w(TAG, " Force finishing activity "
@@ -3670,8 +3662,8 @@ class ActivityStack extends ConfigurationContainer {
final void finishVoiceTask(IVoiceInteractionSession session) {
IBinder sessionBinder = session.asBinder();
boolean didOne = false;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- TaskRecord tr = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ TaskRecord tr = getChildAt(taskNdx);
if (tr.voiceSession != null && tr.voiceSession.asBinder() == sessionBinder) {
for (int activityNdx = tr.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
ActivityRecord r = tr.getChildAt(activityNdx);
@@ -3708,8 +3700,8 @@ class ActivityStack extends ConfigurationContainer {
/** Finish all activities in the stack without waiting. */
void finishAllActivitiesImmediately() {
boolean noActivitiesInStack = true;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
noActivitiesInStack = false;
@@ -3761,7 +3753,7 @@ class ActivityStack extends ConfigurationContainer {
Slog.w(TAG, "shouldUpRecreateTask: task not in history for " + srec);
return false;
}
- final TaskRecord prevTask = mTaskHistory.get(taskIdx);
+ final TaskRecord prevTask = getChildAt(taskIdx);
if (!task.affinity.equals(prevTask.affinity)) {
// These are different apps, so need to recreate.
return true;
@@ -3773,7 +3765,7 @@ class ActivityStack extends ConfigurationContainer {
final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
Intent resultData) {
final TaskRecord task = srec.getTaskRecord();
- final ArrayList<ActivityRecord> activities = task.mActivities;
+ final ArrayList<ActivityRecord> activities = task.mChildren;
final int start = activities.indexOf(srec);
if (!mTaskHistory.contains(task) || (start < 0)) {
return false;
@@ -3867,8 +3859,16 @@ class ActivityStack extends ConfigurationContainer {
* an activity moves away from the stack.
*/
void onActivityRemovedFromStack(ActivityRecord r) {
+ removeActivityFromLRUList(r);
removeTimeoutsForActivity(r);
+ // TODO(stack-unify): null check will no longer be needed.
+ if (mTaskStack != null) {
+ mTaskStack.mExitingActivities.remove(r);
+ }
+ // TODO(stack-unify): Remove if no bugs showed up...
+ //r.mIsExiting = false;
+
if (mResumedActivity != null && mResumedActivity == r) {
setResumedActivity(null, "onActivityRemovedFromStack");
}
@@ -3944,8 +3944,8 @@ class ActivityStack extends ConfigurationContainer {
private void destroyActivitiesLocked(WindowProcessController owner, String reason) {
boolean lastIsOpaque = false;
boolean activityRemoved = false;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (r.finishing) {
@@ -3985,8 +3985,8 @@ class ActivityStack extends ConfigurationContainer {
maxTasks = 1;
}
int numReleased = 0;
- for (int taskNdx = 0; taskNdx < mTaskHistory.size() && maxTasks > 0; taskNdx++) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = 0; taskNdx < getChildCount() && maxTasks > 0; taskNdx++) {
+ final TaskRecord task = getChildAt(taskNdx);
if (!tasks.contains(task)) {
continue;
}
@@ -4009,7 +4009,7 @@ class ActivityStack extends ConfigurationContainer {
if (curNum > 0) {
numReleased += curNum;
maxTasks--;
- if (mTaskHistory.get(taskNdx) != task) {
+ if (getChildAt(taskNdx) != task) {
// The entire task got removed, back up so we don't miss the next one.
taskNdx--;
}
@@ -4060,8 +4060,8 @@ class ActivityStack extends ConfigurationContainer {
int i = numActivities();
if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
"Removing app " + app + " from history with " + i + " entries");
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final ArrayList<ActivityRecord> activities = getChildAt(taskNdx).mChildren;
mTmpActivities.clear();
mTmpActivities.addAll(activities);
@@ -4150,26 +4150,13 @@ class ActivityStack extends ConfigurationContainer {
getDisplay().mDisplayContent.prepareAppTransition(transit, false);
}
- private void updateTaskMovement(TaskRecord task, boolean toFront) {
- if (task.isPersistable) {
- task.mLastTimeMoved = System.currentTimeMillis();
- // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most
- // recently will be most negative, tasks sent to the bottom before that will be less
- // negative. Similarly for recent tasks moved to the top which will be most positive.
- if (!toFront) {
- task.mLastTimeMoved *= -1;
- }
- }
- mRootActivityContainer.invalidateTaskLayers();
- }
-
final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options,
AppTimeTracker timeTracker, String reason) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
final ActivityStack topStack = getDisplay().getTopStack();
final ActivityRecord topActivity = topStack != null ? topStack.getTopActivity() : null;
- final int numTasks = mTaskHistory.size();
+ final int numTasks = getChildCount();
final int index = mTaskHistory.indexOf(tr);
if (numTasks == 0 || index < 0) {
// nothing to do!
@@ -4295,7 +4282,7 @@ class ActivityStack extends ConfigurationContainer {
mTaskHistory.remove(tr);
mTaskHistory.add(0, tr);
- updateTaskMovement(tr, false);
+ tr.updateTaskMovement(false);
getDisplay().mDisplayContent.prepareAppTransition(TRANSIT_TASK_TO_BACK, false);
moveToBack("moveTaskToBackLocked", tr);
@@ -4333,8 +4320,8 @@ class ActivityStack extends ConfigurationContainer {
boolean updatedConfig = false;
for (int taskIndex = mTaskHistory.indexOf(startTask); taskIndex >= 0; --taskIndex) {
- final TaskRecord task = mTaskHistory.get(taskIndex);
- final ArrayList<ActivityRecord> activities = task.mActivities;
+ final TaskRecord task = getChildAt(taskIndex);
+ final ArrayList<ActivityRecord> activities = task.mChildren;
int activityIndex = (start.getTaskRecord() == task)
? activities.indexOf(start) : activities.size() - 1;
for (; activityIndex >= 0; --activityIndex) {
@@ -4370,14 +4357,14 @@ class ActivityStack extends ConfigurationContainer {
try {
// Update override configurations of all tasks in the stack.
final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds;
- for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
- final TaskRecord task = mTaskHistory.get(i);
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ final TaskRecord task = getChildAt(i);
if (task.isResizeable()) {
if (tempTaskInsetBounds != null && !tempTaskInsetBounds.isEmpty()) {
- task.setDisplayedBounds(taskBounds);
+ task.setOverrideDisplayedBounds(taskBounds);
task.setBounds(tempTaskInsetBounds);
} else {
- task.setDisplayedBounds(null);
+ task.setOverrideDisplayedBounds(null);
task.setBounds(taskBounds);
}
}
@@ -4410,8 +4397,8 @@ class ActivityStack extends ConfigurationContainer {
return;
}
- for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
- final TaskRecord task = mTaskHistory.get(i);
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ final TaskRecord task = getChildAt(i);
if (task.isResizeable()) {
task.setBounds(bounds);
} else {
@@ -4426,19 +4413,19 @@ class ActivityStack extends ConfigurationContainer {
return;
}
- for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
- final TaskRecord task = mTaskHistory.get(i);
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ final TaskRecord task = getChildAt(i);
if (bounds == null || bounds.isEmpty()) {
- task.setDisplayedBounds(null);
+ task.setOverrideDisplayedBounds(null);
} else if (task.isResizeable()) {
- task.setDisplayedBounds(bounds);
+ task.setOverrideDisplayedBounds(bounds);
}
}
}
boolean willActivityBeVisibleLocked(IBinder token) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (r.appToken == token) {
@@ -4459,8 +4446,8 @@ class ActivityStack extends ConfigurationContainer {
}
void closeSystemDialogsLocked() {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
@@ -4475,8 +4462,8 @@ class ActivityStack extends ConfigurationContainer {
boolean didSomething = false;
TaskRecord lastTask = null;
ComponentName homeActivity = null;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final ArrayList<ActivityRecord> activities = getChildAt(taskNdx).mChildren;
mTmpActivities.clear();
mTmpActivities.addAll(activities);
@@ -4526,8 +4513,8 @@ class ActivityStack extends ConfigurationContainer {
boolean focusedStack = mRootActivityContainer.getTopDisplayFocusedStack() == this;
boolean topTask = true;
int userId = UserHandle.getUserId(callingUid);
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
if (task.getTopActivity() == null) {
// Skip if there are no activities in the task
continue;
@@ -4566,10 +4553,10 @@ class ActivityStack extends ConfigurationContainer {
}
void unhandledBackLocked() {
- final int top = mTaskHistory.size() - 1;
+ final int top = getChildCount() - 1;
if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Performing unhandledBack(): top activity at " + top);
if (top >= 0) {
- final TaskRecord task = mTaskHistory.get(top);
+ final TaskRecord task = getChildAt(top);
int activityTop = task.getChildCount() - 1;
if (activityTop >= 0) {
task.getChildAt(activityTop).finishIfPossible("unhandled-back", true /* oomAdj */);
@@ -4597,8 +4584,8 @@ class ActivityStack extends ConfigurationContainer {
}
void handleAppCrash(WindowProcessController app) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (r.app == app) {
@@ -4658,12 +4645,12 @@ class ActivityStack extends ConfigurationContainer {
boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
boolean dumpClient, String dumpPackage, boolean needSep) {
- if (mTaskHistory.isEmpty()) {
+ if (!hasChild()) {
return false;
}
final String prefix = " ";
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
if (needSep) {
pw.println("");
}
@@ -4674,7 +4661,7 @@ class ActivityStack extends ConfigurationContainer {
pw.println(prefix + "mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds);
pw.println(prefix + "* " + task);
task.dump(pw, prefix + " ");
- dumpHistoryList(fd, pw, mTaskHistory.get(taskNdx).mActivities,
+ dumpHistoryList(fd, pw, getChildAt(taskNdx).mChildren,
prefix, "Hist", true, !dumpAll, dumpClient, dumpPackage, false, null, task);
}
return true;
@@ -4684,24 +4671,26 @@ class ActivityStack extends ConfigurationContainer {
ArrayList<ActivityRecord> activities = new ArrayList<>();
if ("all".equals(name)) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- activities.addAll(mTaskHistory.get(taskNdx).mActivities);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ activities.addAll(getChildAt(taskNdx).mChildren);
}
} else if ("top".equals(name)) {
- final int top = mTaskHistory.size() - 1;
+ final int top = getChildCount() - 1;
if (top >= 0) {
- final ArrayList<ActivityRecord> list = mTaskHistory.get(top).mActivities;
- int listTop = list.size() - 1;
+ final TaskRecord task = getChildAt(top);
+ int listTop = task.getChildCount() - 1;
if (listTop >= 0) {
- activities.add(list.get(listTop));
+ activities.add(task.getChildAt(listTop));
}
}
} else {
ItemMatcher matcher = new ItemMatcher();
matcher.build(name);
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- for (ActivityRecord r1 : mTaskHistory.get(taskNdx).mActivities) {
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
+ for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+ final ActivityRecord r1 = task.getChildAt(activityNdx);
if (matcher.match(r1, r1.intent.getComponent())) {
activities.add(r1);
}
@@ -4717,8 +4706,8 @@ class ActivityStack extends ConfigurationContainer {
// All activities that came from the package must be
// restarted as if there was a config change.
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord a = task.getChildAt(activityNdx);
if (a.info.packageName.equals(packageName)) {
@@ -4733,58 +4722,51 @@ class ActivityStack extends ConfigurationContainer {
return starting;
}
- /**
- * Removes the input task from this stack.
- *
- * @param task to remove.
- * @param reason for removal.
- * @param mode task removal mode. Either {@link #REMOVE_TASK_MODE_DESTROYING},
- * {@link #REMOVE_TASK_MODE_MOVING}, {@link #REMOVE_TASK_MODE_MOVING_TO_TOP}.
- */
- void removeTask(TaskRecord task, String reason, int mode) {
- if (!mTaskHistory.remove(task)) {
- // Not really in this stack anymore...
- return;
+ // TODO(stack-unify): Merge into removeChild method below.
+ void onChildRemoved(TaskRecord child, DisplayContent dc) {
+ mTaskHistory.remove(child);
+ EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, child.mTaskId, mStackId);
+
+ ActivityDisplay display = getDisplay();
+ if (display == null && dc != null) {
+ display = dc.mActivityDisplay;
}
- EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, task.mTaskId, getStackId());
+ if (display.isSingleTaskInstance()) {
+ mService.notifySingleTaskDisplayEmpty(display.mDisplayId);
+ }
- removeActivitiesFromLRUList(task);
- updateTaskMovement(task, true);
+ display.mDisplayContent.setLayoutNeeded();
- if (mode == REMOVE_TASK_MODE_DESTROYING) {
- task.cleanUpResourcesForDestroy();
+ if (!hasChild()) {
+ // Stack is now empty...
+ remove();
}
+ }
+ /**
+ * Removes the input task from this stack.
+ *
+ * @param task to remove.
+ * @param reason for removal.
+ */
+ void removeChild(TaskRecord task, String reason) {
final ActivityDisplay display = getDisplay();
- if (mTaskHistory.isEmpty()) {
- if (DEBUG_STACK) Slog.i(TAG_STACK, "removeTask: removing stack=" + this);
+ final boolean topFocused = mRootActivityContainer.isTopDisplayFocusedStack(this);
+ mTaskStack.removeChild(task);
+ moveHomeStackToFrontIfNeeded(topFocused, display, reason);
+ }
+
+ void moveHomeStackToFrontIfNeeded(
+ boolean wasTopFocusedStack, ActivityDisplay display, String reason) {
+ if (!hasChild() && wasTopFocusedStack) {
// We only need to adjust focused stack if this stack is in focus and we are not in the
// process of moving the task to the top of the stack that will be focused.
- if (mode != REMOVE_TASK_MODE_MOVING_TO_TOP
- && mRootActivityContainer.isTopDisplayFocusedStack(this)) {
- String myReason = reason + " leftTaskHistoryEmpty";
- if (!inMultiWindowMode() || adjustFocusToNextFocusableStack(myReason) == null) {
- display.moveHomeStackToFront(myReason);
- }
- }
- if (isAttached()) {
- display.positionChildAtBottom(this);
- }
- if (!isActivityTypeHome() || !isAttached()) {
- remove();
+ String myReason = reason + " leftTaskHistoryEmpty";
+ if (!inMultiWindowMode() || adjustFocusToNextFocusableStack(myReason) == null) {
+ display.moveHomeStackToFront(myReason);
}
}
-
- task.setStack(null);
-
- // Notify if a task from the pinned stack is being removed (or moved depending on the mode)
- if (inPinnedWindowingMode()) {
- mService.getTaskChangeNotificationController().notifyActivityUnpinned();
- }
- if (display != null && display.isSingleTaskInstance()) {
- mService.notifySingleTaskDisplayEmpty(display.mDisplayId);
- }
}
TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
@@ -4799,9 +4781,9 @@ class ActivityStack extends ConfigurationContainer {
boolean toTop, ActivityRecord activity, ActivityRecord source,
ActivityOptions options) {
final TaskRecord task = TaskRecord.create(
- mService, taskId, info, intent, voiceSession, voiceInteractor);
+ mService, taskId, info, intent, voiceSession, voiceInteractor, this);
// add the task to stack first, mTaskPositioner might need the stack association
- addTask(task, toTop, "createTaskRecord");
+ addChild(task, toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController()
.isKeyguardOrAodShowing(displayId);
@@ -4810,7 +4792,6 @@ class ActivityStack extends ConfigurationContainer {
&& !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
task.setBounds(getRequestedOverrideBounds());
}
- task.createTask(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
return task;
}
@@ -4818,34 +4799,31 @@ class ActivityStack extends ConfigurationContainer {
return new ArrayList<>(mTaskHistory);
}
- void addTask(final TaskRecord task, final boolean toTop, String reason) {
- addTask(task, toTop ? MAX_VALUE : 0, true /* schedulePictureInPictureModeChange */, reason);
- if (toTop) {
- // TODO: figure-out a way to remove this call.
- positionChildWindowContainerAtTop(task);
- }
+ // TODO(stack-unify): Merge with addChild below.
+ void onChildAdded(TaskRecord task, int position) {
+ final boolean toTop = position >= getChildCount();
+ mTaskHistory.add(position, task);
+
+ // TODO: Feels like this should go in TaskRecord#onParentChanged
+ task.updateTaskMovement(toTop);
}
- // TODO: This shouldn't allow automatic reparenting. Remove the call to preAddTask and deal
- // with the fall-out...
- void addTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange,
- String reason) {
- // TODO: Is this remove really needed? Need to look into the call path for the other addTask
- mTaskHistory.remove(task);
- if (isSingleTaskInstance() && !mTaskHistory.isEmpty()) {
+ void addChild(final TaskRecord task, final boolean toTop, boolean showForAllUsers) {
+ if (isSingleTaskInstance() && hasChild()) {
throw new IllegalStateException("Can only have one child on stack=" + this);
}
- position = getAdjustedPositionForTask(task, position, null /* starting */);
- final boolean toTop = position >= mTaskHistory.size();
- final ActivityStack prevStack = preAddTask(task, reason, toTop);
+ final int position =
+ getAdjustedPositionForTask(task, toTop ? MAX_VALUE : 0, null /* starting */);
- mTaskHistory.add(position, task);
- task.setStack(this);
+ // We only want to move the parents to the parents if we are creating this task at the
+ // top of its stack.
+ mTaskStack.addChild(task, position, showForAllUsers, toTop /*moveParents*/);
- updateTaskMovement(task, toTop);
-
- postAddTask(task, prevStack, schedulePictureInPictureModeChange);
+ if (toTop) {
+ // TODO: figure-out a way to remove this call.
+ positionChildWindowContainerAtTop(task);
+ }
}
void positionChildAt(TaskRecord task, int index) {
@@ -4860,8 +4838,14 @@ class ActivityStack extends ConfigurationContainer {
final ActivityRecord topRunningActivity = task.topRunningActivityLocked();
final boolean wasResumed = topRunningActivity == task.getStack().mResumedActivity;
insertTaskAtPosition(task, index);
- task.setStack(this);
- postAddTask(task, null /* prevStack */, true /* schedulePictureInPictureModeChange */);
+
+ // TODO: Investigate if this random code is really needed.
+ if (task.voiceSession != null) {
+ try {
+ task.voiceSession.taskStarted(task.intent, task.mTaskId);
+ } catch (RemoteException e) {
+ }
+ }
if (wasResumed) {
if (mResumedActivity != null) {
@@ -4878,32 +4862,6 @@ class ActivityStack extends ConfigurationContainer {
mRootActivityContainer.resumeFocusedStacksTopActivities();
}
- private ActivityStack preAddTask(TaskRecord task, String reason, boolean toTop) {
- final ActivityStack prevStack = task.getStack();
- if (prevStack != null && prevStack != this) {
- prevStack.removeTask(task, reason,
- toTop ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
- }
- return prevStack;
- }
-
- /**
- * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
- * change. Callers may set this to false if they are explicitly scheduling PiP mode
- * changes themselves, like during the PiP animation
- */
- private void postAddTask(TaskRecord task, ActivityStack prevStack,
- boolean schedulePictureInPictureModeChange) {
- if (schedulePictureInPictureModeChange && prevStack != null) {
- mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, prevStack);
- } else if (task.voiceSession != null) {
- try {
- task.voiceSession.taskStarted(task.intent, task.mTaskId);
- } catch (RemoteException e) {
- }
- }
- }
-
public void setAlwaysOnTop(boolean alwaysOnTop) {
if (isAlwaysOnTop() == alwaysOnTop) {
return;
@@ -5023,12 +4981,12 @@ class ActivityStack extends ConfigurationContainer {
+ " visible=" + shouldBeVisible(null /* starting */)
+ " translucent=" + isStackTranslucent(null /* starting */)
+ ", "
- + mTaskHistory.size() + " tasks}";
+ + getChildCount() + " tasks}";
}
void onLockTaskPackagesUpdated() {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- mTaskHistory.get(taskNdx).setLockTaskAuth();
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ getChildAt(taskNdx).setLockTaskAuth();
}
}
@@ -5059,8 +5017,8 @@ class ActivityStack extends ConfigurationContainer {
final long token = proto.start(fieldId);
super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
proto.write(ID, mStackId);
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
task.writeToProto(proto, TASKS, logLevel);
}
if (mResumedActivity != null) {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index dc3d2631a5d7..f8a7397f10df 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -52,7 +52,6 @@ import static android.view.WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_IDLE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
@@ -83,6 +82,7 @@ import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
import static com.android.server.wm.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
import android.Manifest;
import android.app.Activity;
@@ -1420,7 +1420,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
// WM resizeTask must be done after the task is moved to the correct stack,
// because Task's setBounds() also updates dim layer's bounds, but that has
// dependency on the stack.
- task.resizeWindowContainer();
+ task.resize(false /* relayout */, false /* forced */);
}
}
@@ -1885,26 +1885,22 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
final ActivityStack stack =
mRootActivityContainer.getLaunchStack(null, aOptions, task, onTop);
final ActivityStack currentStack = task.getStack();
+
+ if (currentStack == stack) {
+ // Nothing else to do since it is already restored in the right stack.
+ return true;
+ }
+
if (currentStack != null) {
- // Task has already been restored once. See if we need to do anything more
- if (currentStack == stack) {
- // Nothing else to do since it is already restored in the right stack.
- return true;
- }
- // Remove current stack association, so we can re-associate the task with the
- // right stack below.
- currentStack.removeTask(task, "restoreRecentTaskLocked", REMOVE_TASK_MODE_MOVING);
+ // Task has already been restored once. Just re-parent it to the new stack.
+ task.reparent(stack.mTaskStack,
+ POSITION_TOP, true /*moveParents*/, "restoreRecentTaskLocked");
+ return true;
}
- stack.addTask(task, onTop, "restoreRecentTask");
- // TODO: move call for creation here and other place into Stack.addTask()
- task.createTask(onTop, true /* showForAllUsers */);
+ stack.addChild(task, onTop, true /* showForAllUsers */);
if (DEBUG_RECENTS) Slog.v(TAG_RECENTS,
"Added restored task=" + task + " to stack=" + stack);
- for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
- final ActivityRecord r = task.getChildAt(activityNdx);
- r.setTask(task);
- }
return true;
}
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 2c4d893dfc39..e2e2b743d011 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.os.FactoryTest.FACTORY_TEST_LOW_LEVEL;
+import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -178,6 +179,13 @@ public class ActivityStartController {
options.setLaunchActivityType(ACTIVITY_TYPE_HOME);
}
options.setLaunchDisplayId(displayId);
+
+ final ActivityDisplay display =
+ mService.mRootActivityContainer.getActivityDisplay(displayId);
+ // Make sure home stack exist on display.
+ final ActivityStack homeStack =
+ display.getOrCreateStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
+
mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
.setOutActivity(tmpOutRecord)
.setCallingUid(0)
@@ -185,10 +193,7 @@ public class ActivityStartController {
.setActivityOptions(options.toBundle())
.execute();
mLastHomeActivityStartRecord = tmpOutRecord[0];
- final ActivityDisplay display =
- mService.mRootActivityContainer.getActivityDisplay(displayId);
- final ActivityStack homeStack = display != null ? display.getHomeStack() : null;
- if (homeStack != null && homeStack.mInResumeTopActivity) {
+ if (homeStack.mInResumeTopActivity) {
// If we are in resume section already, home activity will be initialized, but not
// resumed (to avoid recursive resume) and will stay that way until something pokes it
// again. We need to schedule another resume.
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index d1bb2559e5be..6edcb0298938 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -50,6 +50,7 @@ import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
+import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
@@ -1842,7 +1843,7 @@ class ActivityStarter {
// {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The task
// reference is needed in the call below to {@link setTargetStackAndMoveToFrontIfNeeded}
if (targetTaskTop.getTaskRecord() == null) {
- targetTaskTop.setTask(targetTask);
+ targetTask.addChild(targetTaskTop);
}
if (top != null) {
@@ -1862,8 +1863,8 @@ class ActivityStarter {
// Go ahead and reset it.
mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
mLaunchFlags, mOptions);
- mTargetStack.addTask(targetTask,
- !mLaunchTaskBehind /* toTop */, "complyActivityFlags");
+ mTargetStack.addChild(targetTask, !mLaunchTaskBehind /* toTop */,
+ (mStartActivity.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
}
}
} else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) == 0 && !mAddingToTask
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 222f26edaf5d..a683ccb3f7ff 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -85,7 +85,6 @@ import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.Scr
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.PACKAGE;
import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
@@ -1996,7 +1995,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return false;
}
final TaskRecord task = r.getTaskRecord();
- int index = task.mActivities.lastIndexOf(r);
+ int index = task.mChildren.lastIndexOf(r);
if (index > 0) {
ActivityRecord under = task.getChildAt(index - 1);
under.returningOptions = safeOptions != null ? safeOptions.getOptions(r) : null;
@@ -2221,18 +2220,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
Slog.w(TAG, "getTaskBounds: taskId=" + taskId + " not found");
return rect;
}
- if (task.getStack() != null) {
- // Return the bounds from window manager since it will be adjusted for various
- // things like the presense of a docked stack for tasks that aren't resizeable.
- task.getWindowContainerBounds(rect);
- } else {
- // Task isn't in window manager yet since it isn't associated with a stack.
- // Return the persist value from activity manager
- if (!task.matchParentBounds()) {
- rect.set(task.getBounds());
- } else if (task.mLastNonFullscreenBounds != null) {
- rect.set(task.mLastNonFullscreenBounds);
- }
+ if (task.getParent() != null) {
+ rect.set(task.getBounds());
+ } else if (task.mLastNonFullscreenBounds != null) {
+ rect.set(task.mLastNonFullscreenBounds);
}
}
} finally {
@@ -2249,7 +2240,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final TaskRecord tr = mRootActivityContainer.anyTaskForId(id,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (tr != null) {
- return tr.mTaskDescription;
+ return tr.getTaskDescription();
}
}
return null;
@@ -3168,10 +3159,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
null /* voiceSession */, null /* voiceInteractor */, !ON_TOP);
if (!mRecentTasks.addToBottom(task)) {
// The app has too many tasks already and we can't add any more
- stack.removeTask(task, "addAppTask", REMOVE_TASK_MODE_DESTROYING);
+ stack.removeChild(task, "addAppTask");
return INVALID_TASK_ID;
}
- task.mTaskDescription.copyFrom(description);
+ task.getTaskDescription().copyFrom(description);
// TODO: Send the thumbnail to WM to store it.
@@ -3441,7 +3432,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (stack.inFreeformWindowingMode()) {
stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- } else if (!mSizeCompatFreeform) {
+ } else if (!mSizeCompatFreeform && r.inSizeCompatMode()) {
throw new IllegalStateException("Size-compat windows are currently not"
+ "freeform-enabled");
} else if (stack.getParent().inFreeformWindowingMode()) {
@@ -4489,7 +4480,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
Slog.w(TAG, "cancelTaskWindowTransition: taskId=" + taskId + " not found");
return;
}
- task.cancelWindowTransition();
+ task.cancelTaskWindowTransition();
}
} finally {
Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index cb9a200e6010..cd7c21685e14 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -1922,11 +1922,13 @@ public class AppTransition implements Dump {
if (taskId < 0) {
return null;
}
- ArrayList<Task> tasks = new ArrayList<>();
+ final ArrayList<Task> tasks = new ArrayList<>();
mDisplayContent.forAllTasks(task -> {
if (task.mTaskId == taskId) {
tasks.add(task);
+ return true;
}
+ return false;
});
return tasks.size() == 1 ? tasks.get(0) : null;
}
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 8b4f7cc571f8..30f3bc5e70fb 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -134,9 +134,9 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
onConfigurationChanged(newParentConfig, true /*forwardToChildren*/);
}
- // TODO: Consolidate with onConfigurationChanged() method above once unification is done. This
- // is only currently need during the process of unification where we don't want configuration
- // forwarded to a child from both parents.
+ // TODO(root-unify): Consolidate with onConfigurationChanged() method above once unification is
+ // done. This is only currently need during the process of unification where we don't want
+ // configuration forwarded to a child from both parents.
public void onConfigurationChanged(Configuration newParentConfig, boolean forwardToChildren) {
mResolvedTmpConfig.setTo(mResolvedOverrideConfiguration);
resolveOverrideConfiguration(newParentConfig);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 89568ebf4277..d1d468b5ae3d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2409,7 +2409,19 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
/** Returns true if a removal action is still being deferred. */
@Override
boolean checkCompleteDeferredRemoval() {
- final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval();
+ boolean stillDeferringRemoval = false;
+
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayChildWindowContainer child = getChildAt(i);
+ stillDeferringRemoval |= child.checkCompleteDeferredRemoval();
+ if (getChildCount() == 0) {
+ // If this display is pending to be removed because it contains an activity with
+ // {@link ActivityRecord#mIsExiting} is true, this display may be removed when
+ // completing the removal of the last activity from
+ // {@link ActivityRecord#checkCompleteDeferredRemoval}.
+ return false;
+ }
+ }
if (!stillDeferringRemoval && mDeferredRemoval) {
removeImmediately();
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 6e238b33d8dd..fcfd9ded9ad7 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -144,13 +144,16 @@ import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEventReceiver;
+import android.view.InsetsFlags;
import android.view.InsetsState;
+import android.view.InsetsState.InternalInsetType;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.Surface;
import android.view.View;
import android.view.ViewRootImpl;
import android.view.WindowInsets;
+import android.view.WindowInsetsController.Appearance;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerGlobal;
@@ -332,8 +335,6 @@ public class DisplayPolicy {
private int mResettingSystemUiFlags = 0;
// Bits that we are currently always keeping cleared.
private int mForceClearedSystemUiFlags = 0;
- private int mLastFullscreenStackSysUiFlags;
- private int mLastDockedStackSysUiFlags;
private int mLastAppearance;
private int mLastFullscreenAppearance;
private int mLastDockedAppearance;
@@ -3172,11 +3173,6 @@ public class DisplayPolicy {
&= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
}
- final int appearance = win.mAttrs.insetsFlags.appearance;
- final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
- mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
- final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
- mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
final int fullscreenAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
final int dockedAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
@@ -3190,9 +3186,9 @@ public class DisplayPolicy {
final Pair<Integer, Boolean> result =
updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
final int visibility = result.first;
+ final int appearance = win.mAttrs.insetsFlags.appearance
+ | InsetsFlags.getAppearance(visibility);
final int diff = visibility ^ mLastSystemUiFlags;
- final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
- final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
final InsetsPolicy insetsPolicy = getInsetsPolicy();
final boolean isFullscreen = (visibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)) != 0
@@ -3205,7 +3201,7 @@ public class DisplayPolicy {
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)) != 0
|| behavior == BEHAVIOR_SHOW_BARS_BY_SWIPE
|| behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
- if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0
+ if (diff == 0
&& mLastAppearance == appearance
&& mLastFullscreenAppearance == fullscreenAppearance
&& mLastDockedAppearance == dockedAppearance
@@ -3216,9 +3212,12 @@ public class DisplayPolicy {
&& mLastDockedStackBounds.equals(mDockedStackBounds)) {
return 0;
}
+
+ // Obtains which types should show transient and which types should abort transient.
+ // If there is no transient state change, this pair will contain two empty arrays.
+ final Pair<int[], int[]> transientState = getTransientState(visibility, mLastSystemUiFlags);
+
mLastSystemUiFlags = visibility;
- mLastFullscreenStackSysUiFlags = fullscreenVisibility;
- mLastDockedStackSysUiFlags = dockedVisibility;
mLastAppearance = appearance;
mLastFullscreenAppearance = fullscreenAppearance;
mLastDockedAppearance = dockedAppearance;
@@ -3240,14 +3239,16 @@ public class DisplayPolicy {
StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
if (statusBar != null) {
final int displayId = getDisplayId();
- // TODO(b/118118435): disabled flags only
- statusBar.setSystemUiVisibility(displayId, visibility, fullscreenVisibility,
- dockedVisibility, 0xffffffff, fullscreenStackBounds,
- dockedStackBounds, isNavbarColorManagedByIme, win.toString());
- if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
- statusBar.onSystemBarAppearanceChanged(displayId, appearance,
- appearanceRegions, isNavbarColorManagedByIme);
+ statusBar.setDisableFlags(displayId, visibility & StatusBarManager.DISABLE_MASK,
+ win.toString());
+ if (transientState.first.length > 0) {
+ statusBar.showTransient(displayId, transientState.first);
}
+ if (transientState.second.length > 0) {
+ statusBar.abortTransient(displayId, transientState.second);
+ }
+ statusBar.onSystemBarAppearanceChanged(displayId, appearance,
+ appearanceRegions, isNavbarColorManagedByIme);
statusBar.topAppWindowChanged(displayId, isFullscreen, isImmersive);
// TODO(b/118118435): Remove this after removing system UI visibilities.
@@ -3258,23 +3259,28 @@ public class DisplayPolicy {
return diff;
}
- private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
- final boolean onKeyguard = isStatusBarKeyguard() && !isKeyguardOccluded();
- final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming;
- if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) {
- // If the top fullscreen-or-dimming window is also the top fullscreen, respect
- // its light flag.
- vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
- & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- } else if (statusColorWin != null && statusColorWin.isDimming()) {
- // Otherwise if it's dimming, clear the light flag.
- vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+ private static Pair<int[], int[]> getTransientState(int vis, int oldVis) {
+ final IntArray typesToShow = new IntArray(0);
+ final IntArray typesToAbort = new IntArray(0);
+ updateTransientState(vis, oldVis, View.STATUS_BAR_TRANSIENT, TYPE_TOP_BAR, typesToShow,
+ typesToAbort);
+ updateTransientState(vis, oldVis, View.NAVIGATION_BAR_TRANSIENT,
+ InsetsState.TYPE_NAVIGATION_BAR, typesToShow, typesToAbort);
+ return Pair.create(typesToShow.toArray(), typesToAbort.toArray());
+ }
+
+ private static void updateTransientState(int vis, int oldVis, int transientFlag,
+ @InternalInsetType int type, IntArray typesToShow, IntArray typesToAbort) {
+ final boolean wasTransient = (oldVis & transientFlag) != 0;
+ final boolean isTransient = (vis & transientFlag) != 0;
+ if (!wasTransient && isTransient) {
+ typesToShow.add(type);
+ } else if (wasTransient && !isTransient) {
+ typesToAbort.add(type);
}
- return vis;
}
- private int updateLightStatusBarAppearanceLw(int appearance, WindowState opaque,
+ private int updateLightStatusBarAppearanceLw(@Appearance int appearance, WindowState opaque,
WindowState opaqueOrDimming) {
final boolean onKeyguard = isStatusBarKeyguard() && !isKeyguardOccluded();
final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming;
@@ -3282,7 +3288,10 @@ public class DisplayPolicy {
// If the top fullscreen-or-dimming window is also the top fullscreen, respect
// its light flag.
appearance &= ~APPEARANCE_LIGHT_TOP_BAR;
- appearance |= statusColorWin.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_TOP_BAR;
+ final int legacyAppearance = InsetsFlags.getAppearance(
+ PolicyControl.getSystemUiVisibility(statusColorWin, null));
+ appearance |= (statusColorWin.mAttrs.insetsFlags.appearance | legacyAppearance)
+ & APPEARANCE_LIGHT_TOP_BAR;
} else if (statusColorWin != null && statusColorWin.isDimming()) {
// Otherwise if it's dimming, clear the light flag.
appearance &= ~APPEARANCE_LIGHT_TOP_BAR;
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 2e6df601cf0b..6cb1e763b812 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -291,9 +291,12 @@ class PinnedStackController {
* onTaskStackBoundsChanged() to be called. But we still should update our known display info
* with the new state so that we can update SystemUI.
*/
- synchronized void onDisplayInfoChanged(DisplayInfo displayInfo) {
- setDisplayInfo(displayInfo);
- notifyMovementBoundsChanged(false /* fromImeAdjustment */, false /* fromShelfAdjustment */);
+ void onDisplayInfoChanged(DisplayInfo displayInfo) {
+ synchronized (mService.mGlobalLock) {
+ setDisplayInfo(displayInfo);
+ notifyMovementBoundsChanged(false /* fromImeAdjustment */,
+ false /* fromShelfAdjustment */);
+ }
}
/**
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 2dae12642be3..01cbc5d1e880 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -211,9 +211,9 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
// If there are multiple tasks in the target stack (ie. the home stack, with 3p
// and default launchers coexisting), then move the task to the top as a part of
// moving the stack to the front
- if (targetStack.topTask() != targetActivity.getTaskRecord()) {
- targetStack.addTask(targetActivity.getTaskRecord(), true /* toTop */,
- "startRecentsActivity");
+ final TaskRecord task = targetActivity.getTaskRecord();
+ if (targetStack.topTask() != task) {
+ targetStack.insertTaskAtTop(task, targetActivity);
}
} else {
// No recents activity, create the new recents activity bottom most
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 51a3e7205489..df40419daacd 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -358,7 +358,8 @@ class RootActivityContainer extends ConfigurationContainer
boolean fromHomeKey) {
// Fallback to top focused display if the displayId is invalid.
if (displayId == INVALID_DISPLAY) {
- displayId = getTopDisplayFocusedStack().mDisplayId;
+ final ActivityStack stack = getTopDisplayFocusedStack();
+ displayId = stack != null ? stack.mDisplayId : DEFAULT_DISPLAY;
}
Intent homeIntent = null;
@@ -1265,8 +1266,7 @@ class RootActivityContainer extends ConfigurationContainer
: task.realActivity != null ? task.realActivity.flattenToString()
: task.getTopActivity() != null ? task.getTopActivity().packageName
: "unknown";
- taskBounds[i] = new Rect();
- task.getWindowContainerBounds(taskBounds[i]);
+ taskBounds[i] = mService.getTaskBounds(task.mTaskId);
taskUserIds[i] = task.mUserId;
}
info.taskIds = taskIds;
@@ -1629,7 +1629,7 @@ class RootActivityContainer extends ConfigurationContainer
return false;
}
- <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r,
+ ActivityStack getLaunchStack(@Nullable ActivityRecord r,
@Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop) {
return getLaunchStack(r, options, candidateTask, onTop, null /* launchParams */,
-1 /* no realCallingPid */, -1 /* no realCallingUid */);
@@ -1647,7 +1647,7 @@ class RootActivityContainer extends ConfigurationContainer
*
* @return The stack to use for the launch or INVALID_STACK_ID.
*/
- <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r,
+ ActivityStack getLaunchStack(@Nullable ActivityRecord r,
@Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop,
@Nullable LaunchParamsController.LaunchParams launchParams, int realCallingPid,
int realCallingUid) {
@@ -1675,7 +1675,7 @@ class RootActivityContainer extends ConfigurationContainer
}
final int activityType = resolveActivityType(r, options, candidateTask);
- T stack;
+ ActivityStack stack;
// Next preference for stack goes to the display Id set the candidate display.
if (launchParams != null && launchParams.mPreferredDisplayId != INVALID_DISPLAY) {
@@ -1691,7 +1691,7 @@ class RootActivityContainer extends ConfigurationContainer
if (displayId != INVALID_DISPLAY && (canLaunchOnDisplay(r, displayId)
|| canLaunchOnDisplayFromStartRequest)) {
if (r != null) {
- stack = (T) getValidLaunchStackOnDisplay(displayId, r, candidateTask, options,
+ stack = getValidLaunchStackOnDisplay(displayId, r, candidateTask, options,
launchParams);
if (stack != null) {
return stack;
@@ -1876,7 +1876,12 @@ class RootActivityContainer extends ConfigurationContainer
ActivityStack getNextFocusableStack(@NonNull ActivityStack currentFocus,
boolean ignoreCurrent) {
// First look for next focusable stack on the same display
- final ActivityDisplay preferredDisplay = currentFocus.getDisplay();
+ ActivityDisplay preferredDisplay = currentFocus.getDisplay();
+ if (preferredDisplay == null) {
+ // Stack is currently detached because it is being removed. Use the previous display it
+ // was on.
+ preferredDisplay = getActivityDisplay(currentFocus.mPrevDisplayId);
+ }
final ActivityStack preferredFocusableStack = preferredDisplay.getNextFocusableStack(
currentFocus, ignoreCurrent);
if (preferredFocusableStack != null) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index f5d3affa89ef..149bcfb991ea 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -206,7 +206,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
@Override
- void onChildPositionChanged() {
+ void onChildPositionChanged(WindowContainer child) {
mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
!mWmService.mPerDisplayFocusEnabled /* updateInputWindows */);
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 634990b5fdf2..183ca074ec7f 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityTaskManager.INVALID_STACK_ID;
import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
@@ -24,6 +25,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.res.Configuration.EMPTY;
import static android.view.SurfaceControl.METADATA_TASK_ID;
+import static com.android.server.EventLogTags.WM_TASK_CREATED;
import static com.android.server.EventLogTags.WM_TASK_REMOVED;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
import static com.android.server.wm.TaskProto.APP_WINDOW_TOKENS;
@@ -56,6 +58,7 @@ import android.view.Surface;
import android.view.SurfaceControl;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ToBooleanFunction;
import java.io.PrintWriter;
import java.util.function.Consumer;
@@ -63,17 +66,19 @@ import java.util.function.Consumer;
class Task extends WindowContainer<ActivityRecord> implements ConfigurationContainerListener{
static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_WM;
- // TODO: Track parent marks like this in WindowContainer.
- TaskStack mStack;
+ final ActivityTaskManagerService mAtmService;
+
/* Unique identifier for this task. */
final int mTaskId;
/* User for which this task was created. */
- final int mUserId;
+ // TODO: Make final
+ int mUserId;
final Rect mPreparedFrozenBounds = new Rect();
final Configuration mPreparedFrozenMergedConfig = new Configuration();
// If non-empty, bounds used to display the task during animations/interactions.
+ // TODO(b/119687367): This member is temporary.
private final Rect mOverrideDisplayedBounds = new Rect();
/** ID of the display which rotation {@link #mRotation} has. */
@@ -90,11 +95,12 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
private Rect mTmpRect2 = new Rect();
// Resize mode of the task. See {@link ActivityInfo#resizeMode}
- private int mResizeMode;
+ // Based on the {@link ActivityInfo#resizeMode} of the root activity.
+ int mResizeMode;
- // Whether the task supports picture-in-picture.
- // See {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE}
- private boolean mSupportsPictureInPicture;
+ // Whether or not this task and its activities support PiP. Based on the
+ // {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag of the root activity.
+ boolean mSupportsPictureInPicture;
// Whether the task is currently being drag-resized
private boolean mDragResizing;
@@ -116,78 +122,67 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
/** @see #setCanAffectSystemUiFlags */
private boolean mCanAffectSystemUiFlags = true;
- // TODO: remove after unification
- TaskRecord mTaskRecord;
-
- // TODO: Remove after unification.
- @Override
- public void onConfigurationChanged(Configuration newParentConfig, boolean forwardToChildren) {
- // Forward configuration changes in cases
- // - children won't get it from TaskRecord
- // - it's a pinned task
- forwardToChildren &= (mTaskRecord == null) || inPinnedWindowingMode();
- super.onConfigurationChanged(newParentConfig, forwardToChildren);
- }
-
- Task(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode,
- boolean supportsPictureInPicture, TaskDescription taskDescription,
- TaskRecord taskRecord) {
- super(service);
+ Task(int taskId, TaskStack stack, int userId, int resizeMode, boolean supportsPictureInPicture,
+ TaskDescription taskDescription, ActivityTaskManagerService atm) {
+ super(atm.mWindowManager);
+ mAtmService = atm;
mTaskId = taskId;
- mStack = stack;
mUserId = userId;
mResizeMode = resizeMode;
mSupportsPictureInPicture = supportsPictureInPicture;
- mTaskRecord = taskRecord;
mTaskDescription = taskDescription;
+ EventLog.writeEvent(WM_TASK_CREATED, mTaskId,
+ stack != null ? stack.mStackId : INVALID_STACK_ID);
// Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
setOrientation(SCREEN_ORIENTATION_UNSET);
- if (mTaskRecord != null) {
- // This can be null when we call createTaskInStack in WindowTestUtils. Remove this after
- // unification.
- mTaskRecord.registerConfigurationChangeListener(this);
- } else {
- setBounds(getResolvedOverrideBounds());
- }
+ // TODO(task-merge): Is this really needed?
+ //setBounds(getResolvedOverrideBounds());
}
@Override
DisplayContent getDisplayContent() {
- return mStack != null ? mStack.getDisplayContent() : null;
+ return getTaskStack() != null ? getTaskStack().getDisplayContent() : null;
+ }
+
+ TaskStack getTaskStack() {
+ return (TaskStack) getParent();
}
- private int getAdjustedAddPosition(int suggestedPosition) {
- final int size = mChildren.size();
- if (suggestedPosition >= size) {
- return Math.min(size, suggestedPosition);
+ int getAdjustedAddPosition(ActivityRecord r, int suggestedPosition) {
+ int maxPosition = mChildren.size();
+ if (!r.mTaskOverlay) {
+ // We want to place all non-overlay activities below overlays.
+ while (maxPosition > 0) {
+ final ActivityRecord current = mChildren.get(maxPosition - 1);
+ if (current.mTaskOverlay && !current.removed) {
+ --maxPosition;
+ continue;
+ }
+ break;
+ }
+ if (maxPosition < 0) {
+ maxPosition = 0;
+ }
+ }
+
+ if (suggestedPosition >= maxPosition) {
+ return Math.min(maxPosition, suggestedPosition);
}
- for (int pos = 0; pos < size && pos < suggestedPosition; ++pos) {
+ for (int pos = 0; pos < maxPosition && pos < suggestedPosition; ++pos) {
// TODO: Confirm that this is the behavior we want long term.
if (mChildren.get(pos).removed) {
// suggestedPosition assumes removed tokens are actually gone.
++suggestedPosition;
}
}
- return Math.min(size, suggestedPosition);
- }
-
- @Override
- void addChild(ActivityRecord child, int position) {
- position = getAdjustedAddPosition(position);
- super.addChild(child, position);
-
- // Inform the TaskRecord side of the child addition
- // TODO(task-unify): Will be removed after task unification.
- if (mTaskRecord != null) {
- mTaskRecord.onChildAdded(child, position);
- }
+ return Math.min(maxPosition, suggestedPosition);
}
@Override
void positionChildAt(int position, ActivityRecord child, boolean includingParents) {
- position = getAdjustedAddPosition(position);
+ position = getAdjustedAddPosition(child, position);
super.positionChildAt(position, child, includingParents);
}
@@ -206,7 +201,7 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
// No reason to defer removal of a Task that doesn't have any child.
return false;
}
- return hasWindowsAlive() && mStack.isAnimating(TRANSITION | CHILDREN);
+ return hasWindowsAlive() && getTaskStack().isAnimating(TRANSITION | CHILDREN);
}
@Override
@@ -222,92 +217,40 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
void removeImmediately() {
if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeTask");
- if (mTaskRecord != null) {
- mTaskRecord.unregisterConfigurationChangeListener(this);
- }
-
super.removeImmediately();
}
- void reparent(TaskStack stack, int position, boolean moveParents) {
- if (stack == mStack) {
- throw new IllegalArgumentException(
- "task=" + this + " already child of stack=" + mStack);
- }
- if (stack == null) {
- throw new IllegalArgumentException("reparent: could not find stack.");
- }
+ // TODO: Consolidate this with TaskRecord.reparent()
+ void reparent(TaskStack stack, int position, boolean moveParents, String reason) {
if (DEBUG_STACK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId
- + " from stack=" + mStack);
+ + " from stack=" + getTaskStack());
EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "reParentTask");
- final DisplayContent prevDisplayContent = getDisplayContent();
-
- // If we are moving from the fullscreen stack to the pinned stack
- // then we want to preserve our insets so that there will not
- // be a jump in the area covered by system decorations. We rely
- // on the pinned animation to later unset this value.
- if (stack.inPinnedWindowingMode()) {
- mPreserveNonFloatingState = true;
- } else {
- mPreserveNonFloatingState = false;
- }
-
- getParent().removeChild(this);
- stack.addTask(this, position, showForAllUsers(), moveParents);
- // Relayout display(s).
- final DisplayContent displayContent = stack.getDisplayContent();
- displayContent.setLayoutNeeded();
- if (prevDisplayContent != displayContent) {
- onDisplayChanged(displayContent);
- prevDisplayContent.setLayoutNeeded();
- }
- getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
- }
+ final ActivityStack prevStack = getTaskStack().mActivityStack;
+ final boolean wasTopFocusedStack =
+ mAtmService.mRootActivityContainer.isTopDisplayFocusedStack(prevStack);
+ final ActivityDisplay prevStackDisplay = prevStack.getDisplay();
- /** @see ActivityTaskManagerService#positionTaskInStack(int, int, int). */
- void positionAt(int position) {
- mStack.positionChildAt(position, this, false /* includingParents */);
- }
+ reparent(stack, position);
- @Override
- void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- super.onParentChanged(newParent, oldParent);
-
- // Update task bounds if needed.
- adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
-
- if (getWindowConfiguration().windowsAreScaleable()) {
- // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them
- // while a resize is pending.
- forceWindowsScaleable(true /* force */);
- } else {
- forceWindowsScaleable(false /* force */);
- }
- }
-
- @Override
- void removeChild(ActivityRecord child) {
- if (!mChildren.contains(child)) {
- Slog.e(TAG, "removeChild: token=" + this + " not found.");
- return;
+ if (!moveParents) {
+ // Only move home stack forward if we are not going to move the new parent forward.
+ prevStack.moveHomeStackToFrontIfNeeded(wasTopFocusedStack, prevStackDisplay, reason);
}
- super.removeChild(child);
+ // TODO(task-merge): Remove cast.
+ stack.positionChildAt(position, (TaskRecord) this, moveParents);
- // Inform the TaskRecord side of the child removal
- // TODO(task-unify): Will be removed after task unification.
- if (mTaskRecord != null) {
- mTaskRecord.onChildRemoved(child);
- }
+ // If we are moving from the fullscreen stack to the pinned stack then we want to preserve
+ // our insets so that there will not be a jump in the area covered by system decorations.
+ // We rely on the pinned animation to later unset this value.
+ mPreserveNonFloatingState = stack.inPinnedWindowingMode();
+ }
- // TODO(task-unify): Need to make this account for what we are doing in
- // ActivityRecord.removeFromHistory so that the task isn't removed in some situations when
- // we unify task level.
- if (mChildren.isEmpty()) {
- EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeActivity: last activity");
- removeIfPossible();
- }
+ /** @see ActivityTaskManagerService#positionTaskInStack(int, int, int). */
+ void positionAt(int position) {
+ // TODO(task-merge): Remove cast.
+ getTaskStack().positionChildAt(position, (TaskRecord) this, false /* includingParents */);
}
void setSendingToBottom(boolean toBottom) {
@@ -331,7 +274,8 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
@Override
public int setBounds(Rect bounds) {
int rotation = Surface.ROTATION_0;
- final DisplayContent displayContent = mStack.getDisplayContent();
+ final DisplayContent displayContent = getTaskStack() != null
+ ? getTaskStack().getDisplayContent() : null;
if (displayContent != null) {
rotation = displayContent.getDisplayInfo().rotation;
} else if (bounds == null) {
@@ -355,9 +299,8 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
// No one in higher hierarchy handles this request, let's adjust our bounds to fulfill
// it if possible.
- // TODO: Move to TaskRecord after unification is done.
- if (mTaskRecord != null && mTaskRecord.getParent() != null) {
- mTaskRecord.onConfigurationChanged(mTaskRecord.getParent().getConfiguration());
+ if (getParent() != null) {
+ onConfigurationChanged(getParent().getConfiguration());
return true;
}
return false;
@@ -379,8 +322,9 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
}
/**
- * Sets bounds that override where the task is displayed. Used during transient operations
- * like animation / interaction.
+ * Displayed bounds are used to set where the task is drawn at any given time. This is
+ * separate from its actual bounds so that the app doesn't see any meaningful configuration
+ * changes during transitionary periods.
*/
void setOverrideDisplayedBounds(Rect overrideDisplayedBounds) {
if (overrideDisplayedBounds != null) {
@@ -399,13 +343,13 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
return mOverrideDisplayedBounds;
}
- void setResizeable(int resizeMode) {
- mResizeMode = resizeMode;
+ boolean isResizeable(boolean checkSupportsPip) {
+ return (mAtmService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
+ || (checkSupportsPip && mSupportsPictureInPicture));
}
boolean isResizeable() {
- return ActivityInfo.isResizeableMode(mResizeMode) || mSupportsPictureInPicture
- || mWmService.mAtmService.mForceResizableActivities;
+ return isResizeable(true /* checkSupportsPip */);
}
/**
@@ -462,6 +406,10 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
}
}
+ /**
+ * Gets the current overridden displayed bounds. These will be empty if the task is not
+ * currently overriding where it is displayed.
+ */
@Override
public Rect getDisplayedBounds() {
if (mOverrideDisplayedBounds.isEmpty()) {
@@ -518,7 +466,7 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
/** Bounds of the task to be used for dimming, as well as touch related tests. */
public void getDimBounds(Rect out) {
- final DisplayContent displayContent = mStack.getDisplayContent();
+ final DisplayContent displayContent = getTaskStack().getDisplayContent();
// It doesn't matter if we in particular are part of the resize, since we couldn't have
// a DimLayer anyway if we weren't visible.
final boolean dockedResizing = displayContent != null
@@ -535,9 +483,9 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
// stack bounds and so we don't even want to use them. Even if the app should not be
// resized the Dim should keep up with the divider.
if (dockedResizing) {
- mStack.getBounds(out);
+ getTaskStack().getBounds(out);
} else {
- mStack.getBounds(mTmpRect);
+ getTaskStack().getBounds(mTmpRect);
mTmpRect.intersect(getBounds());
out.set(mTmpRect);
}
@@ -550,9 +498,9 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
void setDragResizing(boolean dragResizing, int dragResizeMode) {
if (mDragResizing != dragResizing) {
// No need to check if the mode is allowed if it's leaving dragResize
- if (dragResizing && !DragResizeMode.isModeAllowedForStack(mStack, dragResizeMode)) {
+ if (dragResizing && !DragResizeMode.isModeAllowedForStack(getTaskStack(), dragResizeMode)) {
throw new IllegalArgumentException("Drag resize mode not allow for stack stackId="
- + mStack.mStackId + " dragResizeMode=" + dragResizeMode);
+ + getTaskStack().mStackId + " dragResizeMode=" + dragResizeMode);
}
mDragResizing = dragResizing;
mDragResizeMode = dragResizeMode;
@@ -577,7 +525,7 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
setDragResizing(resizing, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
}
- private void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) {
+ void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) {
if (displayContent == null) {
return;
}
@@ -618,9 +566,7 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
if (setBounds(mTmpRect2) != BOUNDS_CHANGE_NONE) {
- if (mTaskRecord != null) {
- mTaskRecord.requestResize(getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
- }
+ mAtmService.resizeTask(mTaskId, getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
}
}
@@ -644,7 +590,7 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
*/
boolean isFloating() {
return getWindowConfiguration().tasksAreFloating()
- && !mStack.isAnimatingBoundsToFullscreen() && !mPreserveNonFloatingState;
+ && !getTaskStack().isAnimatingBoundsToFullscreen() && !mPreserveNonFloatingState;
}
@Override
@@ -758,7 +704,8 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
}
void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
- mTaskRecord.onSnapshotChanged(snapshot);
+ mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(
+ mTaskId, snapshot);
}
TaskDescription getTaskDescription() {
@@ -775,6 +722,11 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
callback.accept(this);
}
+ @Override
+ boolean forAllTasks(ToBooleanFunction<Task> callback) {
+ return callback.apply(this);
+ }
+
/**
* @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI
* flags. See {@link WindowState#canAffectSystemUiFlags()}.
@@ -794,11 +746,6 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
mDimmer.dontAnimateExit();
}
- @Override
- public String toString() {
- return "{taskId=" + mTaskId + " appTokens=" + mChildren + "}";
- }
-
String getName() {
return toShortString();
}
@@ -825,9 +772,8 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
}
}
- @CallSuper
- @Override
- public void writeToProto(ProtoOutputStream proto, long fieldId,
+ // TODO(proto-merge): Remove once protos for TaskRecord and Task are merged.
+ void writeToProtoInnerTaskOnly(ProtoOutputStream proto, long fieldId,
@WindowTraceLogLevel int logLevel) {
if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
return;
@@ -843,8 +789,10 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
proto.write(FILLS_PARENT, matchParentBounds());
getBounds().writeToProto(proto, BOUNDS);
mOverrideDisplayedBounds.writeToProto(proto, DISPLAYED_BOUNDS);
- proto.write(SURFACE_WIDTH, mSurfaceControl.getWidth());
- proto.write(SURFACE_HEIGHT, mSurfaceControl.getHeight());
+ if (mSurfaceControl != null) {
+ proto.write(SURFACE_WIDTH, mSurfaceControl.getWidth());
+ proto.write(SURFACE_HEIGHT, mSurfaceControl.getHeight());
+ }
proto.end(token);
}
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 478b1b533f4c..f7b802da8860 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -30,6 +30,7 @@ import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.app.IActivityTaskManager;
import android.graphics.Point;
import android.graphics.Rect;
@@ -104,6 +105,7 @@ class TaskPositioner implements IBinder.DeathRecipient {
@VisibleForTesting
Task mTask;
+ WindowState mWindow;
private boolean mResizing;
private boolean mPreserveOrientation;
private boolean mStartOrientationWasLandscape;
@@ -238,8 +240,9 @@ class TaskPositioner implements IBinder.DeathRecipient {
/**
* @param displayContent The Display that the window being dragged is on.
+ * @param win The window which will be dragged.
*/
- void register(DisplayContent displayContent) {
+ void register(DisplayContent displayContent, @NonNull WindowState win) {
final Display display = displayContent.getDisplay();
if (DEBUG_TASK_POSITIONING) {
@@ -309,6 +312,17 @@ class TaskPositioner implements IBinder.DeathRecipient {
display.getRealSize(mMaxVisibleSize);
mDragEnded = false;
+
+ try {
+ mClientCallback = win.mClient.asBinder();
+ mClientCallback.linkToDeath(this, 0 /* flags */);
+ } catch (RemoteException e) {
+ // The caller has died, so clean up TaskPositioningController.
+ mService.mTaskPositioningController.finishTaskPositioning();
+ return;
+ }
+ mWindow = win;
+ mTask = win.getTask();
}
void unregister() {
@@ -341,25 +355,19 @@ class TaskPositioner implements IBinder.DeathRecipient {
ProtoLog.d(WM_DEBUG_ORIENTATION, "Resuming rotation after re-position");
mDisplayContent.getDisplayRotation().resume();
mDisplayContent = null;
- mClientCallback.unlinkToDeath(this, 0 /* flags */);
+ if (mClientCallback != null) {
+ mClientCallback.unlinkToDeath(this, 0 /* flags */);
+ }
+ mWindow = null;
}
- void startDrag(WindowState win, boolean resize, boolean preserveOrientation, float startX,
- float startY) {
+ void startDrag(boolean resize, boolean preserveOrientation, float startX,
+ float startY) {
if (DEBUG_TASK_POSITIONING) {
- Slog.d(TAG, "startDrag: win=" + win + ", resize=" + resize
+ Slog.d(TAG, "startDrag: win=" + mWindow + ", resize=" + resize
+ ", preserveOrientation=" + preserveOrientation + ", {" + startX + ", "
+ startY + "}");
}
- try {
- mClientCallback = win.mClient.asBinder();
- mClientCallback.linkToDeath(this, 0 /* flags */);
- } catch (RemoteException e) {
- // The caller has died, so clean up TaskPositioningController.
- mService.mTaskPositioningController.finishTaskPositioning();
- return;
- }
- mTask = win.getTask();
// Use the bounds of the task which accounts for
// multiple app windows. Don't use any bounds from win itself as it
// may not be the same size as the task.
@@ -441,7 +449,7 @@ class TaskPositioner implements IBinder.DeathRecipient {
}
// This is a moving or scrolling operation.
- mTask.mStack.getDimBounds(mTmpRect);
+ mTask.getTaskStack().getDimBounds(mTmpRect);
// If a target window is covered by system bar, there is no way to move it again by touch.
// So we exclude them from stack bounds. and then it will be shown inside stable area.
Rect stableBounds = new Rect();
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index e1123fa05b7d..c38e63e54239 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -169,7 +169,7 @@ class TaskPositioningController {
mPositioningDisplay = displayContent;
mTaskPositioner = TaskPositioner.create(mService);
- mTaskPositioner.register(displayContent);
+ mTaskPositioner.register(displayContent, win);
// We need to grab the touch focus so that the touch events during the
// resizing/scrolling are not sent to the app. 'win' is the main window
@@ -187,7 +187,7 @@ class TaskPositioningController {
return false;
}
- mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY);
+ mTaskPositioner.startDrag(resize, preserveOrientation, startX, startY);
return true;
}
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 6920d9d3a770..56f4d32c6183 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -52,11 +52,10 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.server.EventLogTags.WM_TASK_CREATED;
+import static com.android.server.EventLogTags.WM_TASK_REMOVED;
import static com.android.server.am.TaskRecordProto.ACTIVITIES;
import static com.android.server.am.TaskRecordProto.ACTIVITY_TYPE;
import static com.android.server.am.TaskRecordProto.BOUNDS;
-import static com.android.server.am.TaskRecordProto.CONFIGURATION_CONTAINER;
import static com.android.server.am.TaskRecordProto.FULLSCREEN;
import static com.android.server.am.TaskRecordProto.ID;
import static com.android.server.am.TaskRecordProto.LAST_NON_FULLSCREEN_BOUNDS;
@@ -66,11 +65,9 @@ import static com.android.server.am.TaskRecordProto.ORIG_ACTIVITY;
import static com.android.server.am.TaskRecordProto.REAL_ACTIVITY;
import static com.android.server.am.TaskRecordProto.RESIZE_MODE;
import static com.android.server.am.TaskRecordProto.STACK_ID;
+import static com.android.server.am.TaskRecordProto.TASK;
import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REMOVED;
import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
@@ -85,10 +82,6 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static java.lang.Integer.MAX_VALUE;
@@ -143,7 +136,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Objects;
-class TaskRecord extends ConfigurationContainer {
+class TaskRecord extends Task {
private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_ATM;
private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
@@ -212,7 +205,6 @@ class TaskRecord extends ConfigurationContainer {
*/
private static TaskRecordFactory sTaskRecordFactory;
- final int mTaskId; // Unique identifier for this task.
String affinity; // The affinity name for this task, or null; may change identity.
String rootAffinity; // Initial base affinity, or null; does not change from initial root.
final IVoiceInteractionSession voiceSession; // Voice interaction session driving task
@@ -238,17 +230,11 @@ class TaskRecord extends ConfigurationContainer {
boolean hasBeenVisible; // Set if any activities in the task have been visible to the user.
String stringName; // caching of toString() result.
- int mUserId; // user for which this task was created
boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
// was changed.
int numFullscreen; // Number of fullscreen activities.
- int mResizeMode; // The resize mode of this task and its activities.
- // Based on the {@link ActivityInfo#resizeMode} of the root activity.
- private boolean mSupportsPictureInPicture; // Whether or not this task and its activities
- // support PiP. Based on the {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag
- // of the root activity.
/** Can't be put in lockTask mode. */
final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
/** Can enter app pinning with user approval. Can never start over existing lockTask task. */
@@ -264,13 +250,6 @@ class TaskRecord extends ConfigurationContainer {
int mLockTaskUid = -1; // The uid of the application that called startLockTask().
- // This represents the last resolved activity values for this task
- // NOTE: This value needs to be persisted with each task
- TaskDescription mTaskDescription;
-
- /** List of all activities in the task arranged in history order */
- final ArrayList<ActivityRecord> mActivities;
-
/** Current stack. Setter must always be used to update the value. */
private ActivityStack mStack;
@@ -308,8 +287,6 @@ class TaskRecord extends ConfigurationContainer {
int mCallingUid;
String mCallingPackage;
- final ActivityTaskManagerService mAtmService;
-
private final Rect mTmpStableBounds = new Rect();
private final Rect mTmpNonDecorBounds = new Rect();
private final Rect mTmpBounds = new Rect();
@@ -328,17 +305,9 @@ class TaskRecord extends ConfigurationContainer {
// This number will be assigned when we evaluate OOM scores for all visible tasks.
int mLayerRank = -1;
- // When non-empty, this represents the bounds this task will be drawn at. This gets set during
- // transient operations such as split-divider dragging and animations.
- // TODO(b/119687367): This member is temporary.
- final Rect mDisplayedBounds = new Rect();
-
/** Helper object used for updating override configuration. */
private Configuration mTmpConfig = new Configuration();
- // TODO: remove after unification
- Task mTask;
-
/** Used by fillTaskInfo */
final TaskActivitiesReport mReuseActivitiesReport = new TaskActivitiesReport();
@@ -346,21 +315,21 @@ class TaskRecord extends ConfigurationContainer {
* Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
* ActivityInfo, Intent, TaskDescription)} instead.
*/
- TaskRecord(ActivityTaskManagerService atmService, int _taskId, ActivityInfo info,
- Intent _intent, IVoiceInteractionSession _voiceSession,
- IVoiceInteractor _voiceInteractor, TaskDescription _taskDescription) {
+ TaskRecord(ActivityTaskManagerService atmService, int _taskId, ActivityInfo info, Intent _intent,
+ IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
+ TaskDescription _taskDescription, ActivityStack stack) {
this(atmService, _taskId, _intent, null /*_affinityIntent*/, null /*_affinity*/,
null /*_rootAffinity*/, null /*_realActivity*/, null /*_origActivity*/,
false /*_rootWasReset*/, false /*_autoRemoveRecents*/, false /*_askedCompatMode*/,
UserHandle.getUserId(info.applicationInfo.uid), 0 /*_effectiveUid*/,
- null /*_lastDescription*/, new ArrayList<>(), System.currentTimeMillis(),
+ null /*_lastDescription*/, System.currentTimeMillis(),
true /*neverRelinquishIdentity*/,
_taskDescription != null ? _taskDescription : new TaskDescription(),
_taskId, INVALID_TASK_ID, INVALID_TASK_ID, 0 /*taskAffiliationColor*/,
info.applicationInfo.uid, info.packageName, info.resizeMode,
info.supportsPictureInPicture(), false /*_realActivitySuspended*/,
false /*userSetupComplete*/, INVALID_MIN_SIZE, INVALID_MIN_SIZE, info,
- _voiceSession, _voiceInteractor);
+ _voiceSession, _voiceInteractor, stack);
}
/** Don't use constructor directly. This is only used by XML parser. */
@@ -368,15 +337,16 @@ class TaskRecord extends ConfigurationContainer {
Intent _affinityIntent, String _affinity, String _rootAffinity,
ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId,
- int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
+ int _effectiveUid, String _lastDescription,
long lastTimeMoved, boolean neverRelinquishIdentity,
TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended,
boolean userSetupComplete, int minWidth, int minHeight, ActivityInfo info,
- IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
- mAtmService = atmService;
- mTaskId = _taskId;
+ IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
+ ActivityStack stack) {
+ super(_taskId, stack != null ? stack.mTaskStack : null, _userId, resizeMode,
+ supportsPictureInPicture, _lastTaskDescription, atmService);
mRemoteToken = new RemoteToken(this);
affinityIntent = _affinityIntent;
affinity = _affinity;
@@ -390,15 +360,12 @@ class TaskRecord extends ConfigurationContainer {
isAvailable = true;
autoRemoveRecents = _autoRemoveRecents;
askedCompatMode = _askedCompatMode;
- mUserId = _userId;
mUserSetupComplete = userSetupComplete;
effectiveUid = _effectiveUid;
touchActiveTime();
lastDescription = _lastDescription;
- mActivities = activities;
mLastTimeMoved = lastTimeMoved;
mNeverRelinquishIdentity = neverRelinquishIdentity;
- mTaskDescription = _lastTaskDescription;
mAffiliatedTaskId = taskAffiliation;
mAffiliatedTaskColor = taskAffiliationColor;
mPrevAffiliateTaskId = prevTaskId;
@@ -406,7 +373,6 @@ class TaskRecord extends ConfigurationContainer {
mCallingUid = callingUid;
mCallingPackage = callingPackage;
mResizeMode = resizeMode;
- mSupportsPictureInPicture = supportsPictureInPicture;
if (info != null) {
setIntent(_intent, info);
setMinDimensions(info);
@@ -418,39 +384,6 @@ class TaskRecord extends ConfigurationContainer {
mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
}
- Task getTask() {
- return mTask;
- }
-
- void createTask(boolean onTop, boolean showForAllUsers) {
- if (mTask != null) {
- throw new IllegalArgumentException("mTask=" + mTask
- + " already created for task=" + this);
- }
-
- final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
- final TaskStack stack = getStack().getTaskStack();
-
- if (stack == null) {
- throw new IllegalArgumentException("TaskRecord: invalid stack=" + mStack);
- }
- EventLog.writeEvent(WM_TASK_CREATED, mTaskId, stack.mStackId);
- mTask = new Task(mTaskId, stack, mUserId, mAtmService.mWindowManager, mResizeMode,
- mSupportsPictureInPicture, mTaskDescription, this);
- final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
-
- if (!mDisplayedBounds.isEmpty()) {
- mTask.setOverrideDisplayedBounds(mDisplayedBounds);
- }
- // We only want to move the parents to the parents if we are creating this task at the
- // top of its stack.
- stack.addTask(mTask, position, showForAllUsers, onTop /* moveParents */);
- }
-
- void setTask(Task task) {
- mTask = task;
- }
-
void cleanUpResourcesForDestroy() {
if (hasChild()) {
return;
@@ -473,60 +406,33 @@ class TaskRecord extends ConfigurationContainer {
mAtmService.mStackSupervisor.mRecentTasks.remove(this);
}
- removeWindowContainer();
+ removeIfPossible();
}
@VisibleForTesting
- void removeWindowContainer() {
+ @Override
+ void removeIfPossible() {
mAtmService.getLockTaskController().clearLockedTask(this);
- if (mTask == null) {
- if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + mTaskId);
- return;
- }
- mTask.removeIfPossible();
- mTask = null;
- if (!getWindowConfiguration().persistTaskBounds()) {
- // Reset current bounds for task whose bounds shouldn't be persisted so it uses
- // default configuration the next time it launches.
- setBounds(null);
- }
+ super.removeIfPossible();
mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId);
}
- void onSnapshotChanged(TaskSnapshot snapshot) {
- mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(mTaskId, snapshot);
- }
-
void setResizeMode(int resizeMode) {
if (mResizeMode == resizeMode) {
return;
}
mResizeMode = resizeMode;
- mTask.setResizeable(resizeMode);
mAtmService.mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
mAtmService.mRootActivityContainer.resumeFocusedStacksTopActivities();
}
- void setTaskDockedResizing(boolean resizing) {
- if (mTask == null) {
- Slog.w(TAG_WM, "setTaskDockedResizing: taskId " + mTaskId + " not found.");
- return;
- }
- mTask.setTaskDockedResizing(resizing);
- }
-
- // TODO: Consolidate this with the resize() method below.
- public void requestResize(Rect bounds, int resizeMode) {
- mAtmService.resizeTask(mTaskId, bounds, resizeMode);
- }
-
boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
mAtmService.deferWindowLayout();
try {
final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
- if (mTask == null) {
+ if (getParent() == null) {
// Task doesn't exist in window manager yet (e.g. was restored from recents).
// All we can do for now is update the bounds so it can be used when the task is
// added to window manager.
@@ -577,7 +483,7 @@ class TaskRecord extends ConfigurationContainer {
}
}
}
- mTask.resize(kept, forced);
+ resize(kept, forced);
saveLaunchingStateIfNeeded();
@@ -588,19 +494,6 @@ class TaskRecord extends ConfigurationContainer {
}
}
- // TODO: Investigate combining with the resize() method above.
- void resizeWindowContainer() {
- mTask.resize(false /* relayout */, false /* forced */);
- }
-
- void getWindowContainerBounds(Rect bounds) {
- if (mTask != null) {
- mTask.getBounds(bounds);
- } else {
- bounds.setEmpty();
- }
- }
-
/**
* Convenience method to reparent a task to the top or bottom position of the stack.
*/
@@ -708,32 +601,16 @@ class TaskRecord extends ConfigurationContainer {
// Adjust the position for the new parent stack as needed.
position = toStack.getAdjustedPositionForTask(this, position, null /* starting */);
- // Must reparent first in window manager to avoid a situation where AM can delete the
- // we are coming from in WM before we reparent because it became empty.
- mTask.reparent(toStack.getTaskStack(), position,
- moveStackMode == REPARENT_MOVE_STACK_TO_FRONT);
-
final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
|| (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
- // Move the task
- sourceStack.removeTask(this, reason, moveStackToFront
- ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
- toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason);
+
+ reparent(toStack.getTaskStack(), position, moveStackToFront, reason);
if (schedulePictureInPictureModeChange) {
// Notify of picture-in-picture mode changes
supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
}
- // TODO: Ensure that this is actually necessary here
- // Notify the voice session if required
- if (voiceSession != null) {
- try {
- voiceSession.taskStarted(intent, mTaskId);
- } catch (RemoteException e) {
- }
- }
-
// If the task had focus before (or we're requested to move focus), move focus to the
// new stack by moving the stack to the front.
if (r != null) {
@@ -809,14 +686,6 @@ class TaskRecord extends ConfigurationContainer {
|| targetWindowingMode == WINDOWING_MODE_FREEFORM;
}
- void cancelWindowTransition() {
- if (mTask == null) {
- Slog.w(TAG_WM, "cancelWindowTransition: taskId " + mTaskId + " not found.");
- return;
- }
- mTask.cancelTaskWindowTransition();
- }
-
/**
* DO NOT HOLD THE ACTIVITY MANAGER LOCK WHEN CALLING THIS METHOD!
*/
@@ -966,69 +835,107 @@ class TaskRecord extends ConfigurationContainer {
mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.mTaskId;
}
- <T extends ActivityStack> T getStack() {
- return (T) mStack;
+ ActivityStack getStack() {
+ return mStack;
+ }
+
+ // TODO(stack-unify): Can be removed on stack unified.
+ void onParentChanged(ActivityStack newParent, ActivityStack oldParent) {
+ onParentChanged(
+ newParent != null ? newParent.mTaskStack : null,
+ oldParent != null ? oldParent.mTaskStack : null);
}
- /**
- * Must be used for setting parent stack because it performs configuration updates.
- * Must be called after adding task as a child to the stack.
- */
- // TODO(task-unify): Remove or rework after task level unification.
- void setStack(ActivityStack stack) {
- if (stack != null && !stack.isInStackLocked(this)) {
- throw new IllegalStateException("Task must be added as a Stack child first.");
- }
- final ActivityStack oldStack = mStack;
- mStack = stack;
+ @Override
+ void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
+ final ActivityStack oldStack = (oldParent != null)
+ ? ((TaskStack) oldParent).mActivityStack : null;
+ final ActivityStack newStack = (newParent != null)
+ ? ((TaskStack) newParent).mActivityStack : null;
+
+ mStack = newStack;
- // If the new {@link TaskRecord} is from a different {@link ActivityStack}, remove this
- // {@link ActivityRecord} from its current {@link ActivityStack}.
+ super.onParentChanged(newParent, oldParent);
- if (oldStack != mStack) {
+ if (oldStack != null) {
for (int i = getChildCount() - 1; i >= 0; --i) {
final ActivityRecord activity = getChildAt(i);
+ oldStack.onActivityRemovedFromStack(activity);
+ }
- if (oldStack != null) {
- oldStack.onActivityRemovedFromStack(activity);
- }
+ updateTaskMovement(true /*toFront*/);
- if (mStack != null) {
- stack.onActivityAddedToStack(activity);
+ if (oldStack.inPinnedWindowingMode()
+ && (newStack == null || !newStack.inPinnedWindowingMode())) {
+ // Notify if a task from the pinned stack is being removed
+ // (or moved depending on the mode).
+ mAtmService.getTaskChangeNotificationController().notifyActivityUnpinned();
+ }
+ }
+
+ if (newStack != null) {
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final ActivityRecord activity = getChildAt(i);
+ newStack.onActivityAddedToStack(activity);
+ }
+
+ // TODO: Ensure that this is actually necessary here
+ // Notify the voice session if required
+ if (voiceSession != null) {
+ try {
+ voiceSession.taskStarted(intent, mTaskId);
+ } catch (RemoteException e) {
}
}
}
- onParentChanged(mStack, oldStack);
- }
+ // First time we are adding the task to the system.
+ if (oldParent == null && newParent != null) {
- /**
- * @return Id of current stack, {@link INVALID_STACK_ID} if no stack is set.
- */
- int getStackId() {
- return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
- }
+ // TODO: Super random place to be doing this, but aligns with what used to be done
+ // before we unified Task level. Look into if this can be done in a better place.
+ updateOverrideConfigurationFromLaunchBounds();
+ }
- @Override
- protected int getChildCount() {
- return mActivities.size();
- }
+ // Task is being removed.
+ if (oldParent != null && newParent == null) {
+ cleanUpResourcesForDestroy();
+ }
- @Override
- protected ActivityRecord getChildAt(int index) {
- return mActivities.get(index);
+
+ // Update task bounds if needed.
+ adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
+
+ if (getWindowConfiguration().windowsAreScaleable()) {
+ // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them
+ // while a resize is pending.
+ forceWindowsScaleable(true /* force */);
+ } else {
+ forceWindowsScaleable(false /* force */);
+ }
+
+ mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
}
- @Override
- protected ConfigurationContainer getParent() {
- return mStack;
+ /** TODO(task-merge): Consolidate into {@link TaskStack#onChildPositionChanged}. */
+ void updateTaskMovement(boolean toFront) {
+ if (isPersistable) {
+ mLastTimeMoved = System.currentTimeMillis();
+ // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most
+ // recently will be most negative, tasks sent to the bottom before that will be less
+ // negative. Similarly for recent tasks moved to the top which will be most positive.
+ if (!toFront) {
+ mLastTimeMoved *= -1;
+ }
+ }
+ mAtmService.mRootActivityContainer.invalidateTaskLayers();
}
- @Override
- protected void onParentChanged(
- ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- super.onParentChanged(newParent, oldParent);
- mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
+ /**
+ * @return Id of current stack, {@link ActivityTaskManager#INVALID_STACK_ID} if no stack is set.
+ */
+ int getStackId() {
+ return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
}
// Close up recents linked list.
@@ -1121,16 +1028,6 @@ class TaskRecord extends ConfigurationContainer {
return null;
}
- boolean isVisible() {
- for (int i = getChildCount() - 1; i >= 0; --i) {
- final ActivityRecord r = getChildAt(i);
- if (r.visible) {
- return true;
- }
- }
- return false;
- }
-
/**
* Return true if any activities in this task belongs to input uid.
*/
@@ -1210,15 +1107,10 @@ class TaskRecord extends ConfigurationContainer {
* Reorder the history stack so that the passed activity is brought to the front.
*/
final void moveActivityToFrontLocked(ActivityRecord newTop) {
- if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
- "Removing and adding activity " + newTop
- + " to stack at top callers=" + Debug.getCallers(4));
-
- mActivities.remove(newTop);
- mActivities.add(newTop);
+ if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, "Removing and adding activity "
+ + newTop + " to stack at top callers=" + Debug.getCallers(4));
- // Make sure window manager is aware of the position change.
- mTask.positionChildAtTop(newTop);
+ positionChildAtTop(newTop);
updateEffectiveIntent();
}
@@ -1232,19 +1124,29 @@ class TaskRecord extends ConfigurationContainer {
return getChildAt(0).getActivityType();
}
- /** Called when a Task child is added from the Task.java side. */
- // TODO(task-unify): Just override addChild to do what is needed when someone calls to add a
- // child.
- void onChildAdded(ActivityRecord r, int index) {
+ @Override
+ void addChild(ActivityRecord r, int index) {
+ if (r.getParent() != null) {
+ // Shouldn't already have a parent since we are just adding to the task...Maybe you
+ // meant to use reparent?
+ throw new IllegalStateException(
+ "r=" + r + " parent=" + r.getParent() + " task=" + this);
+ }
+
+ // If this task had any child before we added this one.
+ boolean hadChild = hasChild();
+
+ index = getAdjustedAddPosition(r, index);
+ super.addChild(r, index);
+
+ ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);
r.inHistory = true;
- // Remove r first, and if it wasn't already in the list and it's fullscreen, count it.
- if (!mActivities.remove(r) && r.occludesParent()) {
- // Was not previously in list.
+ if (r.occludesParent()) {
numFullscreen++;
}
// Only set this based on the first activity
- if (!hasChild()) {
+ if (!hadChild) {
if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
// Normally non-standard activity type for the activity record will be set when the
// object is created, however we delay setting the standard application type until
@@ -1264,20 +1166,6 @@ class TaskRecord extends ConfigurationContainer {
r.setActivityType(getActivityType());
}
- final int size = getChildCount();
-
- if (index == size && size > 0) {
- final ActivityRecord top = getChildAt(size - 1);
- if (top.mTaskOverlay) {
- // Place below the task overlay activity since the overlay activity should always
- // be on top.
- index--;
- }
- }
-
- index = Math.min(size, index);
- mActivities.add(index, r);
-
updateEffectiveIntent();
if (r.isPersistable()) {
mAtmService.notifyTaskPersisterLocked(this, false);
@@ -1288,31 +1176,23 @@ class TaskRecord extends ConfigurationContainer {
mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
}
- // TODO(task-unify): Merge onChildAdded method below into this since task will be a single
- // object.
void addChild(ActivityRecord r) {
- if (r.getParent() != null) {
- // Shouldn't already have a parent since we are just adding to the task...
- throw new IllegalStateException(
- "r=" + r + " parent=" + r.getParent() + " task=" + this);
- }
+ addChild(r, Integer.MAX_VALUE /* add on top */);
+ }
- ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);
- // This means the activity isn't attached to Task.java yet. Go ahead and do that.
- // TODO(task-unify): Remove/call super once we unify task level.
- if (mTask != null) {
- mTask.addChild(r, Integer.MAX_VALUE /* add on top */);
- } else {
- onChildAdded(r, Integer.MAX_VALUE);
- }
+ @Override
+ void removeChild(ActivityRecord r) {
+ removeChild(r, "removeChild");
}
- /** Called when a Task child is removed from the Task.java side. */
- // TODO(task-unify): Just override removeChild to do what is needed when someone calls to remove
- // a child.
- void onChildRemoved(ActivityRecord r) {
- if (mActivities.remove(r) && r.occludesParent()) {
- // Was previously in list.
+ void removeChild(ActivityRecord r, String reason) {
+ if (!mChildren.contains(r)) {
+ Slog.e(TAG, "removeChild: r=" + r + " not found in t=" + this);
+ return;
+ }
+
+ super.removeChild(r);
+ if (r.occludesParent()) {
numFullscreen--;
}
if (r.isPersistable()) {
@@ -1336,16 +1216,19 @@ class TaskRecord extends ConfigurationContainer {
// When destroying a task, tell the supervisor to remove it so that any activity it
// has can be cleaned up correctly. This is currently the only place where we remove
// a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
- // state into removeTask(), we just clear the task here before the other residual
+ // state into removeChild(), we just clear the task here before the other residual
// work.
- // TODO: If the callers to removeTask() changes such that we have multiple places
- // where we are destroying the task, move this back into removeTask()
+ // TODO: If the callers to removeChild() changes such that we have multiple places
+ // where we are destroying the task, move this back into removeChild()
mAtmService.mStackSupervisor.removeTaskByIdLocked(mTaskId, false /* killProcess */,
- !REMOVE_FROM_RECENTS, "onChildRemoved");
+ !REMOVE_FROM_RECENTS, reason);
}
} else if (!mReuseTask) {
// Remove entire task if it doesn't have any activity left and it isn't marked for reuse
- mStack.removeTask(this, "onChildRemoved", REMOVE_TASK_MODE_DESTROYING);
+ mStack.removeChild(this, reason);
+ EventLog.writeEvent(WM_TASK_REMOVED, mTaskId,
+ "removeChild: last r=" + r + " in t=" + this);
+ removeIfPossible();
}
}
@@ -1380,7 +1263,7 @@ class TaskRecord extends ConfigurationContainer {
* Completely remove all activities associated with an existing
* task starting at a specified index.
*/
- final void performClearTaskAtIndexLocked(int activityNdx, String reason) {
+ private void performClearTaskAtIndexLocked(int activityNdx, String reason) {
int numActivities = getChildCount();
for ( ; activityNdx < numActivities; ++activityNdx) {
final ActivityRecord r = getChildAt(activityNdx);
@@ -1390,7 +1273,7 @@ class TaskRecord extends ConfigurationContainer {
if (mStack == null) {
// Task was restored from persistent storage.
r.takeFromHistory();
- mActivities.remove(activityNdx);
+ removeChild(r);
--activityNdx;
--numActivities;
} else if (r.finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason,
@@ -1526,20 +1409,13 @@ class TaskRecord extends ConfigurationContainer {
" mLockTaskAuth=" + lockTaskAuthToString());
}
- private boolean isResizeable(boolean checkSupportsPip) {
- return (mAtmService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
- || (checkSupportsPip && mSupportsPictureInPicture));
- }
-
- boolean isResizeable() {
- return isResizeable(true /* checkSupportsPip */);
- }
-
@Override
public boolean supportsSplitScreenWindowingMode() {
// A task can not be docked even if it is considered resizeable because it only supports
// picture-in-picture mode but has a non-resizeable resizeMode
return super.supportsSplitScreenWindowingMode()
+ // TODO(task-group): Probably makes sense to move this and associated code into
+ // WindowContainer so it affects every node.
&& mAtmService.mSupportsSplitScreenMultiWindow
&& (mAtmService.mForceResizableActivities
|| (isResizeable(false /* checkSupportsPip */)
@@ -1672,15 +1548,13 @@ class TaskRecord extends ConfigurationContainer {
}
topActivity = false;
}
- mTaskDescription = new TaskDescription(label, null, iconResource, iconFilename,
- colorPrimary, colorBackground, statusBarColor, navigationBarColor,
+ final TaskDescription taskDescription = new TaskDescription(label, null, iconResource,
+ iconFilename, colorPrimary, colorBackground, statusBarColor, navigationBarColor,
statusBarContrastWhenTransparent, navigationBarContrastWhenTransparent);
- if (mTask != null) {
- mTask.setTaskDescription(mTaskDescription);
- }
+ setTaskDescription(taskDescription);
// Update the task affiliation color if we are the parent of the group
if (mTaskId == mAffiliatedTaskId) {
- mAffiliatedTaskColor = mTaskDescription.getPrimaryColor();
+ mAffiliatedTaskColor = taskDescription.getPrimaryColor();
}
}
}
@@ -1903,38 +1777,6 @@ class TaskRecord extends ConfigurationContainer {
}
/**
- * Displayed bounds are used to set where the task is drawn at any given time. This is
- * separate from its actual bounds so that the app doesn't see any meaningful configuration
- * changes during transitionary periods.
- */
- void setDisplayedBounds(Rect bounds) {
- if (bounds == null) {
- mDisplayedBounds.setEmpty();
- } else {
- mDisplayedBounds.set(bounds);
- }
- if (mTask != null) {
- mTask.setOverrideDisplayedBounds(
- mDisplayedBounds.isEmpty() ? null : mDisplayedBounds);
- }
- }
-
- /**
- * Gets the current overridden displayed bounds. These will be empty if the task is not
- * currently overriding where it is displayed.
- */
- Rect getDisplayedBounds() {
- return mDisplayedBounds;
- }
-
- /**
- * @return {@code true} if this has overridden displayed bounds.
- */
- boolean hasDisplayedBounds() {
- return !mDisplayedBounds.isEmpty();
- }
-
- /**
* Intersects inOutBounds with intersectBounds-intersectInsets. If inOutBounds is larger than
* intersectBounds on a side, then the respective side will not be intersected.
*
@@ -2190,16 +2032,10 @@ class TaskRecord extends ConfigurationContainer {
computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
}
- /** @see WindowContainer#handlesOrientationChangeFromDescendant */
- boolean handlesOrientationChangeFromDescendant() {
- return mTask != null && mTask.getParent() != null
- && mTask.getParent().handlesOrientationChangeFromDescendant();
- }
-
/**
- * Compute bounds (letterbox or pillarbox) for {@link #WINDOWING_MODE_FULLSCREEN} when the
- * parent doesn't handle the orientation change and the requested orientation is different from
- * the parent.
+ * Compute bounds (letterbox or pillarbox) for
+ * {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN} when the parent doesn't handle the
+ * orientation change and the requested orientation is different from the parent.
*/
void computeFullscreenBounds(@NonNull Rect outBounds, @Nullable ActivityRecord refActivity,
@NonNull Rect parentBounds, int parentOrientation) {
@@ -2345,7 +2181,7 @@ class TaskRecord extends ConfigurationContainer {
info.realActivity = realActivity;
info.numActivities = mReuseActivitiesReport.numActivities;
info.lastActiveTime = lastActiveTime;
- info.taskDescription = new ActivityManager.TaskDescription(mTaskDescription);
+ info.taskDescription = new ActivityManager.TaskDescription(getTaskDescription());
info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
info.resizeMode = mResizeMode;
info.configuration.setTo(getConfiguration());
@@ -2435,7 +2271,7 @@ class TaskRecord extends ConfigurationContainer {
}
pw.println(")");
}
- pw.print(prefix); pw.print("Activities="); pw.println(mActivities);
+ pw.print(prefix); pw.print("Activities="); pw.println(mChildren);
if (!askedCompatMode || !inRecents || !isAvailable) {
pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
pw.print(" inRecents="); pw.print(inRecents);
@@ -2490,6 +2326,7 @@ class TaskRecord extends ConfigurationContainer {
return toString();
}
+ @Override
public void writeToProto(ProtoOutputStream proto, long fieldId,
@WindowTraceLogLevel int logLevel) {
if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
@@ -2497,13 +2334,13 @@ class TaskRecord extends ConfigurationContainer {
}
final long token = proto.start(fieldId);
- super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
+ writeToProtoInnerTaskOnly(proto, TASK, logLevel);
proto.write(ID, mTaskId);
for (int i = getChildCount() - 1; i >= 0; i--) {
- ActivityRecord activity = getChildAt(i);
+ final ActivityRecord activity = getChildAt(i);
activity.writeToProto(proto, ACTIVITIES);
}
- proto.write(STACK_ID, mStack.mStackId);
+ proto.write(STACK_ID, getStackId());
if (mLastNonFullscreenBounds != null) {
mLastNonFullscreenBounds.writeToProto(proto, LAST_NON_FULLSCREEN_BOUNDS);
}
@@ -2579,8 +2416,8 @@ class TaskRecord extends ConfigurationContainer {
if (lastDescription != null) {
out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
}
- if (mTaskDescription != null) {
- mTaskDescription.saveToXml(out);
+ if (getTaskDescription() != null) {
+ getTaskDescription().saveToXml(out);
}
out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
@@ -2641,14 +2478,14 @@ class TaskRecord extends ConfigurationContainer {
static TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Intent intent, IVoiceInteractionSession voiceSession,
- IVoiceInteractor voiceInteractor) {
+ IVoiceInteractor voiceInteractor, ActivityStack stack) {
return getTaskRecordFactory().create(
- service, taskId, info, intent, voiceSession, voiceInteractor);
+ service, taskId, info, intent, voiceSession, voiceInteractor, stack);
}
static TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
- Intent intent, TaskDescription taskDescription) {
- return getTaskRecordFactory().create(service, taskId, info, intent, taskDescription);
+ Intent intent, TaskDescription taskDescription, ActivityStack stack) {
+ return getTaskRecordFactory().create(service, taskId, info, intent, taskDescription, stack);
}
static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
@@ -2665,15 +2502,15 @@ class TaskRecord extends ConfigurationContainer {
TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Intent intent, IVoiceInteractionSession voiceSession,
- IVoiceInteractor voiceInteractor) {
+ IVoiceInteractor voiceInteractor, ActivityStack stack) {
return new TaskRecord(service, taskId, info, intent, voiceSession, voiceInteractor,
- null /*taskDescription*/);
+ null /*taskDescription*/, stack);
}
TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
- Intent intent, TaskDescription taskDescription) {
+ Intent intent, TaskDescription taskDescription, ActivityStack stack) {
return new TaskRecord(service, taskId, info, intent, null /*voiceSession*/,
- null /*voiceInteractor*/, taskDescription);
+ null /*voiceInteractor*/, taskDescription, stack);
}
/**
@@ -2683,20 +2520,20 @@ class TaskRecord extends ConfigurationContainer {
Intent affinityIntent, String affinity, String rootAffinity,
ComponentName realActivity, ComponentName origActivity, boolean rootWasReset,
boolean autoRemoveRecents, boolean askedCompatMode, int userId,
- int effectiveUid, String lastDescription, ArrayList<ActivityRecord> activities,
+ int effectiveUid, String lastDescription,
long lastTimeMoved, boolean neverRelinquishIdentity,
TaskDescription lastTaskDescription, int taskAffiliation, int prevTaskId,
int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
int resizeMode, boolean supportsPictureInPicture, boolean realActivitySuspended,
- boolean userSetupComplete, int minWidth, int minHeight) {
+ boolean userSetupComplete, int minWidth, int minHeight, ActivityStack stack) {
return new TaskRecord(service, taskId, intent, affinityIntent, affinity,
rootAffinity, realActivity, origActivity, rootWasReset, autoRemoveRecents,
- askedCompatMode, userId, effectiveUid, lastDescription, activities,
+ askedCompatMode, userId, effectiveUid, lastDescription,
lastTimeMoved, neverRelinquishIdentity, lastTaskDescription, taskAffiliation,
prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
resizeMode, supportsPictureInPicture, realActivitySuspended, userSetupComplete,
minWidth, minHeight, null /*ActivityInfo*/, null /*_voiceSession*/,
- null /*_voiceInteractor*/);
+ null /*_voiceInteractor*/, stack);
}
TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
@@ -2908,15 +2745,15 @@ class TaskRecord extends ConfigurationContainer {
taskId, intent, affinityIntent,
affinity, rootAffinity, realActivity, origActivity, rootHasReset,
autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
- activities, lastTimeOnTop, neverRelinquishIdentity, taskDescription,
+ lastTimeOnTop, neverRelinquishIdentity, taskDescription,
taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
callingPackage, resizeMode, supportsPictureInPicture, realActivitySuspended,
- userSetupComplete, minWidth, minHeight);
+ userSetupComplete, minWidth, minHeight, null /*stack*/);
task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
task.setBounds(lastNonFullscreenBounds);
for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
- activities.get(activityNdx).setTask(task);
+ task.addChild(activities.get(activityNdx));
}
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 56211e25f421..e82525ae8c96 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -84,7 +84,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
-public class TaskStack extends WindowContainer<Task> implements
+public class TaskStack extends WindowContainer<TaskRecord> implements
BoundsAnimationTarget, ConfigurationContainerListener {
/** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to
* restrict IME adjustment so that a min portion of top stack remains visible.*/
@@ -102,7 +102,6 @@ public class TaskStack extends WindowContainer<Task> implements
private Rect mTmpRect3 = new Rect();
/** For Pinned stack controlling. */
- private Rect mTmpFromBounds = new Rect();
private Rect mTmpToBounds = new Rect();
/** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */
@@ -116,7 +115,6 @@ public class TaskStack extends WindowContainer<Task> implements
/** ActivityRecords that are exiting, but still on screen for animations. */
final ArrayList<ActivityRecord> mExitingActivities = new ArrayList<>();
- final ArrayList<ActivityRecord> mTmpActivities = new ArrayList<>();
/** Detach this stack from its display when animation completes. */
// TODO: maybe tie this to WindowContainer#removeChild some how...
@@ -330,7 +328,7 @@ public class TaskStack extends WindowContainer<Task> implements
}
/** Bounds of the stack with other system factors taken into consideration. */
- public void getDimBounds(Rect out) {
+ void getDimBounds(Rect out) {
getBounds(out);
}
@@ -482,11 +480,6 @@ public class TaskStack extends WindowContainer<Task> implements
dividerSize);
}
- // TODO: Checkout the call points of this method and the ones below to see how they can fit in WC.
- void addTask(Task task, int position) {
- addTask(task, position, task.showForAllUsers(), true /* moveParents */);
- }
-
/**
* Put a Task in this stack. Used for adding only.
* When task is added to top of the stack, the entire branch of the hierarchy (including stack
@@ -495,22 +488,19 @@ public class TaskStack extends WindowContainer<Task> implements
* @param position Target position to add the task to.
* @param showForAllUsers Whether to show the task regardless of the current user.
*/
- void addTask(Task task, int position, boolean showForAllUsers, boolean moveParents) {
- final TaskStack currentStack = task.mStack;
- // TODO: We pass stack to task's constructor, but we still need to call this method.
- // This doesn't make sense, mStack will already be set equal to "this" at this point.
- if (currentStack != null && currentStack.mStackId != mStackId) {
- throw new IllegalStateException("Trying to add taskId=" + task.mTaskId
- + " to stackId=" + mStackId
- + ", but it is already attached to stackId=" + task.mStack.mStackId);
- }
-
+ void addChild(TaskRecord task, int position, boolean showForAllUsers, boolean moveParents) {
// Add child task.
- task.mStack = this;
addChild(task, null);
// Move child to a proper position, as some restriction for position might apply.
- positionChildAt(position, task, moveParents /* includingParents */, showForAllUsers);
+ position = positionChildAt(
+ position, task, moveParents /* includingParents */, showForAllUsers);
+ mActivityStack.onChildAdded(task, position);
+ }
+
+ @Override
+ void addChild(TaskRecord task, int position) {
+ addChild(task, position, task.showForAllUsers(), false /* includingParents */);
}
void positionChildAt(Task child, int position) {
@@ -527,7 +517,7 @@ public class TaskStack extends WindowContainer<Task> implements
getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
}
- void positionChildAtTop(Task child, boolean includingParents) {
+ void positionChildAtTop(TaskRecord child, boolean includingParents) {
if (child == null) {
// TODO: Fix the call-points that cause this to happen.
return;
@@ -542,7 +532,7 @@ public class TaskStack extends WindowContainer<Task> implements
displayContent.layoutAndAssignWindowLayersIfNeeded();
}
- void positionChildAtBottom(Task child, boolean includingParents) {
+ void positionChildAtBottom(TaskRecord child, boolean includingParents) {
if (child == null) {
// TODO: Fix the call-points that cause this to happen.
return;
@@ -557,19 +547,18 @@ public class TaskStack extends WindowContainer<Task> implements
}
@Override
- void positionChildAt(int position, Task child, boolean includingParents) {
+ void positionChildAt(int position, TaskRecord child, boolean includingParents) {
positionChildAt(position, child, includingParents, child.showForAllUsers());
}
/**
* Overridden version of {@link TaskStack#positionChildAt(int, Task, boolean)}. Used in
- * {@link TaskStack#addTask(Task, int, boolean showForAllUsers, boolean)}, as it can receive
- * showForAllUsers param from {@link AppWindowToken} instead of {@link Task#showForAllUsers()}.
+ * {@link TaskStack#addChild(Task, int, boolean showForAllUsers, boolean)}, as it can receive
+ * showForAllUsers param from {@link ActivityRecord} instead of {@link Task#showForAllUsers()}.
*/
- private void positionChildAt(int position, Task child, boolean includingParents,
+ int positionChildAt(int position, TaskRecord child, boolean includingParents,
boolean showForAllUsers) {
- final int targetPosition = findPositionForTask(child, position, showForAllUsers,
- false /* addingNew */);
+ final int targetPosition = findPositionForTask(child, position, showForAllUsers);
super.positionChildAt(targetPosition, child, includingParents);
// Log positioning.
@@ -578,6 +567,14 @@ public class TaskStack extends WindowContainer<Task> implements
final int toTop = targetPosition == mChildren.size() - 1 ? 1 : 0;
EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, child.mTaskId, toTop, targetPosition);
+
+ return targetPosition;
+ }
+
+ @Override
+ void onChildPositionChanged(WindowContainer child) {
+ // TODO(task-merge): Read comment on updateTaskMovement method.
+ //((TaskRecord) child).updateTaskMovement(true);
}
void reparent(int displayId, Rect outStackBounds, boolean onTop) {
@@ -597,14 +594,13 @@ public class TaskStack extends WindowContainer<Task> implements
// TODO: We should really have users as a window container in the hierarchy so that we don't
// have to do complicated things like we are doing in this method.
- private int findPositionForTask(Task task, int targetPosition, boolean showForAllUsers,
- boolean addingNew) {
+ private int findPositionForTask(Task task, int targetPosition, boolean showForAllUsers) {
final boolean canShowTask =
showForAllUsers || mWmService.isCurrentProfileLocked(task.mUserId);
final int stackSize = mChildren.size();
int minPosition = 0;
- int maxPosition = addingNew ? stackSize : stackSize - 1;
+ int maxPosition = stackSize - 1;
if (canShowTask) {
minPosition = computeMinPosition(minPosition, stackSize);
@@ -615,8 +611,7 @@ public class TaskStack extends WindowContainer<Task> implements
// preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid.
if (targetPosition == POSITION_BOTTOM && minPosition == 0) {
return POSITION_BOTTOM;
- } else if (targetPosition == POSITION_TOP
- && maxPosition == (addingNew ? stackSize : stackSize - 1)) {
+ } else if (targetPosition == POSITION_TOP && maxPosition == (stackSize - 1)) {
return POSITION_TOP;
}
// Reset position based on minimum/maximum possible positions.
@@ -668,25 +663,16 @@ public class TaskStack extends WindowContainer<Task> implements
* @param task The Task to delete.
*/
@Override
- void removeChild(Task task) {
+ void removeChild(TaskRecord task) {
+ if (!mChildren.contains(task)) {
+ // Not really in this stack anymore...
+ return;
+ }
if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "removeChild: task=" + task);
super.removeChild(task);
- task.mStack = null;
- if (mDisplayContent != null) {
- if (mChildren.isEmpty()) {
- getParent().positionChildAt(POSITION_BOTTOM, this, false /* includingParents */);
- }
- mDisplayContent.setLayoutNeeded();
- }
- for (int appNdx = mExitingActivities.size() - 1; appNdx >= 0; --appNdx) {
- final ActivityRecord activity = mExitingActivities.get(appNdx);
- if (activity.getTask() == task) {
- activity.mIsExiting = false;
- mExitingActivities.remove(appNdx);
- }
- }
+ mActivityStack.onChildRemoved(task, mDisplayContent);
}
@Override
@@ -972,7 +958,7 @@ public class TaskStack extends WindowContainer<Task> implements
super.switchUser();
int top = mChildren.size();
for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
- Task task = mChildren.get(taskNdx);
+ TaskRecord task = mChildren.get(taskNdx);
if (mWmService.isCurrentProfileLocked(task.mUserId) || task.showForAllUsers()) {
mChildren.remove(taskNdx);
mChildren.add(task);
@@ -1298,7 +1284,7 @@ public class TaskStack extends WindowContainer<Task> implements
super.writeToProto(proto, WINDOW_CONTAINER, logLevel);
proto.write(ID, mStackId);
for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
- mChildren.get(taskNdx).writeToProto(proto, TASKS, logLevel);
+ mChildren.get(taskNdx).writeToProtoInnerTaskOnly(proto, TASKS, logLevel);
}
proto.write(FILLS_PARENT, matchParentBounds());
getRawBounds().writeToProto(proto, BOUNDS);
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 7ce2b5eb727b..11658f944e8a 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -237,7 +237,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
* This gets used during some open/close transitions as well as during a change transition
* where it represents the starting-state snapshot.
*/
- AppWindowThumbnail mThumbnail;
+ WindowContainerThumbnail mThumbnail;
final Rect mTransitStartRect = new Rect();
final Point mTmpPoint = new Point();
protected final Rect mTmpRect = new Rect();
@@ -428,7 +428,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
parent.mTreeWeight += child.mTreeWeight;
parent = parent.getParent();
}
- onChildPositionChanged();
+ onChildPositionChanged(child);
}
/**
@@ -454,7 +454,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
parent.mTreeWeight -= child.mTreeWeight;
parent = parent.getParent();
}
- onChildPositionChanged();
+ onChildPositionChanged(child);
}
/**
@@ -583,7 +583,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
if (mChildren.peekLast() != child) {
mChildren.remove(child);
mChildren.add(child);
- onChildPositionChanged();
+ onChildPositionChanged(child);
}
if (includingParents && getParent() != null) {
getParent().positionChildAt(POSITION_TOP, this /* child */,
@@ -594,7 +594,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
if (mChildren.peekFirst() != child) {
mChildren.remove(child);
mChildren.addFirst(child);
- onChildPositionChanged();
+ onChildPositionChanged(child);
}
if (includingParents && getParent() != null) {
getParent().positionChildAt(POSITION_BOTTOM, this /* child */,
@@ -608,14 +608,14 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
// doing this adjustment here and remove any adjustments in the callers.
mChildren.remove(child);
mChildren.add(position, child);
- onChildPositionChanged();
+ onChildPositionChanged(child);
}
}
/**
* Notify that a child's position has changed. Possible changes are adding or removing a child.
*/
- void onChildPositionChanged() { }
+ void onChildPositionChanged(WindowContainer child) { }
/**
* Update override configuration and recalculate full config.
@@ -1121,6 +1121,21 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
}
}
+ /**
+ * For all tasks at or below this container call the callback.
+ *
+ * @param callback Calls the {@link ToBooleanFunction#apply} method for each task found and
+ * stops the search if {@link ToBooleanFunction#apply} returns {@code true}.
+ */
+ boolean forAllTasks(ToBooleanFunction<Task> callback) {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ if (mChildren.get(i).forAllTasks(callback)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
WindowState getWindow(Predicate<WindowState> callback) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowState w = mChildren.get(i).getWindow(callback);
@@ -1520,8 +1535,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WC#applyAnimation");
if (okToAnimate()) {
- Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp, transit,
- enter, isVoiceInteraction);
+ final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
+ transit, enter, isVoiceInteraction);
AnimationAdapter adapter = adapters.first;
AnimationAdapter thumbnailAdapter = adapters.second;
if (adapter != null) {
@@ -1580,18 +1595,16 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
- AnimationAdapter adapter = new LocalAnimationAdapter(
+ final AnimationAdapter adapter = new LocalAnimationAdapter(
new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect, displayInfo,
durationScale, true /* isAppAnimation */, false /* isThumbnail */),
getSurfaceAnimationRunner());
- AnimationAdapter thumbnailAdapter = null;
- if (mThumbnail != null) {
- thumbnailAdapter = new LocalAnimationAdapter(
- new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect, displayInfo,
- durationScale, true /* isAppAnimation */, true /* isThumbnail */),
- getSurfaceAnimationRunner());
- }
+ final AnimationAdapter thumbnailAdapter = mThumbnail != null
+ ? new LocalAnimationAdapter(new WindowChangeAnimationSpec(mTransitStartRect,
+ mTmpRect, displayInfo, durationScale, true /* isAppAnimation */,
+ true /* isThumbnail */), getSurfaceAnimationRunner())
+ : null;
resultAdapters = new Pair<>(adapter, thumbnailAdapter);
mTransit = transit;
mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/WindowContainerThumbnail.java
index acd96e916fa8..604eae6a5427 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/WindowContainerThumbnail.java
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
package com.android.server.wm;
@@ -19,10 +19,10 @@ package com.android.server.wm;
import static android.view.SurfaceControl.METADATA_OWNER_UID;
import static android.view.SurfaceControl.METADATA_WINDOW_TYPE;
-import static com.android.server.wm.AppWindowThumbnailProto.HEIGHT;
-import static com.android.server.wm.AppWindowThumbnailProto.SURFACE_ANIMATOR;
-import static com.android.server.wm.AppWindowThumbnailProto.WIDTH;
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.server.wm.WindowContainerThumbnailProto.HEIGHT;
+import static com.android.server.wm.WindowContainerThumbnailProto.SURFACE_ANIMATOR;
+import static com.android.server.wm.WindowContainerThumbnailProto.WIDTH;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
@@ -30,7 +30,7 @@ import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
import android.graphics.GraphicBuffer;
import android.graphics.PixelFormat;
import android.graphics.Point;
-import android.os.Binder;
+import android.os.Process;
import android.util.proto.ProtoOutputStream;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -44,39 +44,40 @@ import com.android.server.wm.SurfaceAnimator.Animatable;
import java.util.function.Supplier;
/**
- * Represents a surface that is displayed over an {@link ActivityRecord}
+ * Represents a surface that is displayed over a subclass of {@link WindowContainer}
*/
-class AppWindowThumbnail implements Animatable {
+class WindowContainerThumbnail implements Animatable {
- private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowThumbnail" : TAG_WM;
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainerThumbnail" : TAG_WM;
- private final ActivityRecord mActivityRecord;
+ private final WindowContainer mWindowContainer;
private SurfaceControl mSurfaceControl;
private final SurfaceAnimator mSurfaceAnimator;
private final int mWidth;
private final int mHeight;
private final boolean mRelative;
- AppWindowThumbnail(Supplier<Surface> surfaceFactory, Transaction t, ActivityRecord activity,
- GraphicBuffer thumbnailHeader) {
- this(surfaceFactory, t, activity, thumbnailHeader, false /* relative */);
+ WindowContainerThumbnail(Supplier<Surface> surfaceFactory, Transaction t,
+ WindowContainer container, GraphicBuffer thumbnailHeader) {
+ this(surfaceFactory, t, container, thumbnailHeader, false /* relative */);
}
/**
* @param t Transaction to create the thumbnail in.
- * @param activity {@link ActivityRecord} to associate this thumbnail with.
+ * @param container The sub-class of {@link WindowContainer} to associate this thumbnail with.
* @param thumbnailHeader A thumbnail or placeholder for thumbnail to initialize with.
- * @param relative Whether this thumbnail will be a child of activity (and thus positioned
+ * @param relative Whether this thumbnail will be a child of the container (and thus positioned
* relative to it) or not.
*/
- AppWindowThumbnail(Supplier<Surface> surfaceFactory, Transaction t, ActivityRecord activity,
- GraphicBuffer thumbnailHeader, boolean relative) {
- this(t, activity, thumbnailHeader, relative, surfaceFactory.get(), null);
+ WindowContainerThumbnail(Supplier<Surface> surfaceFactory, Transaction t,
+ WindowContainer container, GraphicBuffer thumbnailHeader, boolean relative) {
+ this(t, container, thumbnailHeader, relative, surfaceFactory.get(), null);
}
- AppWindowThumbnail(Transaction t, ActivityRecord activity, GraphicBuffer thumbnailHeader,
- boolean relative, Surface drawSurface, SurfaceAnimator animator) {
- mActivityRecord = activity;
+ WindowContainerThumbnail(Transaction t, WindowContainer container,
+ GraphicBuffer thumbnailHeader, boolean relative, Surface drawSurface,
+ SurfaceAnimator animator) {
+ mWindowContainer = container;
mRelative = relative;
if (animator != null) {
mSurfaceAnimator = animator;
@@ -84,24 +85,21 @@ class AppWindowThumbnail implements Animatable {
// We can't use a delegating constructor since we need to
// reference this::onAnimationFinished
mSurfaceAnimator =
- new SurfaceAnimator(this, this::onAnimationFinished, activity.mWmService);
+ new SurfaceAnimator(this, this::onAnimationFinished, container.mWmService);
}
mWidth = thumbnailHeader.getWidth();
mHeight = thumbnailHeader.getHeight();
// Create a new surface for the thumbnail
- WindowState window = mActivityRecord.findMainWindow();
-
// TODO: This should be attached as a child to the app token, once the thumbnail animations
// use relative coordinates. Once we start animating task we can also consider attaching
// this to the task.
- mSurfaceControl = mActivityRecord.makeSurface()
- .setName("thumbnail anim: " + mActivityRecord.toString())
+ mSurfaceControl = mWindowContainer.makeSurface()
+ .setName("thumbnail anim: " + mWindowContainer.toString())
.setBufferSize(mWidth, mHeight)
.setFormat(PixelFormat.TRANSLUCENT)
- .setMetadata(METADATA_WINDOW_TYPE, mActivityRecord.windowType)
- .setMetadata(METADATA_OWNER_UID,
- window != null ? window.mOwnerUid : Binder.getCallingUid())
+ .setMetadata(METADATA_WINDOW_TYPE, mWindowContainer.getWindowingMode())
+ .setMetadata(METADATA_OWNER_UID, Process.myUid())
.build();
ProtoLog.i(WM_SHOW_TRANSACTIONS, " THUMBNAIL %s: CREATE", mSurfaceControl);
@@ -112,11 +110,11 @@ class AppWindowThumbnail implements Animatable {
drawSurface.release();
t.show(mSurfaceControl);
- // We parent the thumbnail to the task, and just place it on top of anything else in the
- // task.
+ // We parent the thumbnail to the container, and just place it on top of anything else in
+ // the container.
t.setLayer(mSurfaceControl, Integer.MAX_VALUE);
if (relative) {
- t.reparent(mSurfaceControl, mActivityRecord.getSurfaceControl());
+ t.reparent(mSurfaceControl, mWindowContainer.getSurfaceControl());
}
}
@@ -126,12 +124,12 @@ class AppWindowThumbnail implements Animatable {
void startAnimation(Transaction t, Animation anim, Point position) {
anim.restrictDuration(MAX_ANIMATION_DURATION);
- anim.scaleCurrentDuration(mActivityRecord.mWmService.getTransitionAnimationScaleLocked());
+ anim.scaleCurrentDuration(mWindowContainer.mWmService.getTransitionAnimationScaleLocked());
mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter(
new WindowAnimationSpec(anim, position,
- mActivityRecord.getDisplayContent().mAppTransition.canSkipFirstFrame(),
- mActivityRecord.getDisplayContent().getWindowCornerRadius()),
- mActivityRecord.mWmService.mSurfaceAnimationRunner), false /* hidden */);
+ mWindowContainer.getDisplayContent().mAppTransition.canSkipFirstFrame(),
+ mWindowContainer.getDisplayContent().getWindowCornerRadius()),
+ mWindowContainer.mWmService.mSurfaceAnimationRunner), false /* hidden */);
}
/**
@@ -161,10 +159,11 @@ class AppWindowThumbnail implements Animatable {
/**
* Write to a protocol buffer output stream. Protocol buffer message definition is at {@link
- * com.android.server.wm.AppWindowThumbnailProto}.
+ * com.android.server.wm.WindowContainerThumbnailProto}.
*
- * @param proto Stream to write the AppWindowThumbnail object to.
- * @param fieldId Field Id of the AppWindowThumbnail as defined in the parent message.
+ * @param proto Stream to write the WindowContainerThumbnailProto object to.
+ * @param fieldId Field Id of the WindowContainerThumbnailProto as defined in the parent
+ * message.
* @hide
*/
void writeToProto(ProtoOutputStream proto, long fieldId) {
@@ -179,19 +178,19 @@ class AppWindowThumbnail implements Animatable {
@Override
public Transaction getPendingTransaction() {
- return mActivityRecord.getPendingTransaction();
+ return mWindowContainer.getPendingTransaction();
}
@Override
public void commitPendingTransaction() {
- mActivityRecord.commitPendingTransaction();
+ mWindowContainer.commitPendingTransaction();
}
@Override
public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
t.setLayer(leash, Integer.MAX_VALUE);
if (mRelative) {
- t.reparent(leash, mActivityRecord.getSurfaceControl());
+ t.reparent(leash, mWindowContainer.getSurfaceControl());
}
}
@@ -205,7 +204,7 @@ class AppWindowThumbnail implements Animatable {
@Override
public Builder makeAnimationLeash() {
- return mActivityRecord.makeSurface();
+ return mWindowContainer.makeSurface();
}
@Override
@@ -215,12 +214,12 @@ class AppWindowThumbnail implements Animatable {
@Override
public SurfaceControl getAnimationLeashParent() {
- return mActivityRecord.getAppAnimationLayer();
+ return mWindowContainer.getAnimationLeashParent();
}
@Override
public SurfaceControl getParentSurfaceControl() {
- return mActivityRecord.getParentSurfaceControl();
+ return mWindowContainer.getParentSurfaceControl();
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index ab937e0a4e23..2c56b1124f9f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -4361,7 +4361,7 @@ public class WindowManagerService extends IWindowManager.Stub
final DisplayContent topFocusedDisplay = mRoot.getTopFocusedDisplayContent();
final ActivityRecord focusedApp = topFocusedDisplay.mFocusedApp;
return (focusedApp != null && focusedApp.getTask() != null)
- ? focusedApp.getTask().mStack : null;
+ ? focusedApp.getTask().getTaskStack() : null;
}
public boolean detectSafeMode() {
@@ -7657,7 +7657,7 @@ public class WindowManagerService extends IWindowManager.Stub
return;
}
- final TaskStack stack = task.mStack;
+ final TaskStack stack = task.getTaskStack();
// We ignore home stack since we don't want home stack to move to front when touched.
// Specifically, in freeform we don't want tapping on home to cause the freeform apps to go
// behind home. See b/117376413
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 1d11acd61a68..d196c3425d0d 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -638,7 +638,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
private boolean mIsDimming = false;
private @Nullable InsetsSourceProvider mControllableInsetProvider;
- private InsetsState mClientInsetsState = new InsetsState();
+ private InsetsState mClientInsetsState;
private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
private KeyInterceptionInfo mKeyInterceptionInfo;
@@ -767,6 +767,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mSeq = seq;
mPowerManagerWrapper = powerManagerWrapper;
mForceSeamlesslyRotate = token.mRoundedCornerOverlay;
+ mClientInsetsState =
+ getDisplayContent().getInsetsStateController().getInsetsForDispatch(this);
if (DEBUG) {
Slog.v(TAG, "Window " + this + " client=" + c.asBinder()
+ " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
@@ -1281,7 +1283,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// notify the client of frame changes in this case. Not only is it a lot of churn, but
// the frame may not correspond to the surface size or the onscreen area at various
// phases in the animation, and the client will become sad and confused.
- if (task != null && task.mStack.isAnimatingBounds()) {
+ if (task != null && task.getTaskStack().isAnimatingBounds()) {
return;
}
@@ -1421,8 +1423,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
TaskStack getStack() {
Task task = getTask();
if (task != null) {
- if (task.mStack != null) {
- return task.mStack;
+ if (task.getTaskStack() != null) {
+ return task.getTaskStack();
}
}
// Some system windows (e.g. "Power off" dialog) don't have a task, but we would still
@@ -1441,7 +1443,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
bounds.setEmpty();
mTmpRect.setEmpty();
if (intersectWithStackBounds) {
- final TaskStack stack = task.mStack;
+ final TaskStack stack = task.getTaskStack();
if (stack != null) {
stack.getDimBounds(mTmpRect);
} else {
@@ -1843,8 +1845,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
final int top = mWindowFrames.mFrame.top;
final Task task = getTask();
final boolean adjustedForMinimizedDockOrIme = task != null
- && (task.mStack.isAdjustedForMinimizedDockedStack()
- || task.mStack.isAdjustedForIme());
+ && (task.getTaskStack().isAdjustedForMinimizedDockedStack()
+ || task.getTaskStack().isAdjustedForIme());
if (mToken.okToAnimate()
&& (mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
&& !isDragResizing() && !adjustedForMinimizedDockOrIme
@@ -1880,7 +1882,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
boolean isObscuringDisplay() {
Task task = getTask();
- if (task != null && task.mStack != null && !task.mStack.fillsParent()) {
+ if (task != null && task.getTaskStack() != null && !task.getTaskStack().fillsParent()) {
return false;
}
return isOpaqueDrawn() && fillsDisplay();
@@ -2299,8 +2301,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
void applyAdjustForImeIfNeeded() {
final Task task = getTask();
- if (task != null && task.mStack != null && task.mStack.isAdjustedForIme()) {
- task.mStack.applyAdjustForImeIfNeeded(task);
+ if (task != null && task.getTaskStack() != null && task.getTaskStack().isAdjustedForIme()) {
+ task.getTaskStack().applyAdjustForImeIfNeeded(task);
}
}
@@ -2631,7 +2633,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return false;
}
- return mActivityRecord.getTask().mStack.shouldIgnoreInput()
+ return mActivityRecord.getTask().getTaskStack().shouldIgnoreInput()
|| mActivityRecord.hiddenRequested
|| isAnimatingToRecents();
}
@@ -3151,7 +3153,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return;
}
- final TaskStack stack = task.mStack;
+ final TaskStack stack = task.getTaskStack();
if (stack == null) {
return;
}
@@ -3165,7 +3167,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return;
}
- final TaskStack stack = task.mStack;
+ final TaskStack stack = task.getTaskStack();
if (stack == null) {
return;
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index fef3a9d362eb..a853828317c9 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -892,10 +892,10 @@ class WindowStateAnimator {
int posX = 0;
int posY = 0;
- task.mStack.getDimBounds(mTmpStackBounds);
+ task.getTaskStack().getDimBounds(mTmpStackBounds);
boolean allowStretching = false;
- task.mStack.getFinalAnimationSourceHintBounds(mTmpSourceBounds);
+ task.getTaskStack().getFinalAnimationSourceHintBounds(mTmpSourceBounds);
// If we don't have source bounds, we can attempt to use the content insets
// in the following scenario:
// 1. We have content insets.
@@ -905,8 +905,8 @@ class WindowStateAnimator {
// because of the force-scale until resize state.
if (mTmpSourceBounds.isEmpty() && (mWin.mLastRelayoutContentInsets.width() > 0
|| mWin.mLastRelayoutContentInsets.height() > 0)
- && !task.mStack.lastAnimatingBoundsWasToFullscreen()) {
- mTmpSourceBounds.set(task.mStack.mPreAnimationBounds);
+ && !task.getTaskStack().lastAnimatingBoundsWasToFullscreen()) {
+ mTmpSourceBounds.set(task.getTaskStack().mPreAnimationBounds);
mTmpSourceBounds.inset(mWin.mLastRelayoutContentInsets);
allowStretching = true;
}
@@ -920,7 +920,7 @@ class WindowStateAnimator {
if (!mTmpSourceBounds.isEmpty()) {
// Get the final target stack bounds, if we are not animating, this is just the
// current stack bounds
- task.mStack.getFinalAnimationBounds(mTmpAnimatingBounds);
+ task.getTaskStack().getFinalAnimationBounds(mTmpAnimatingBounds);
// Calculate the current progress and interpolate the difference between the target
// and source bounds
@@ -1499,7 +1499,7 @@ class WindowStateAnimator {
*/
boolean isForceScaled() {
final Task task = mWin.getTask();
- if (task != null && task.mStack.isForceScaled()) {
+ if (task != null && task.getTaskStack().isForceScaled()) {
return true;
}
return mForceScaleUntilResize;
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index da355ea0ca3b..425b4b632971 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -23,7 +23,6 @@ cc_library_static {
"com_android_server_AlarmManagerService.cpp",
"com_android_server_am_BatteryStatsService.cpp",
"com_android_server_connectivity_Vpn.cpp",
- "com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp",
"com_android_server_ConsumerIrService.cpp",
"com_android_server_devicepolicy_CryptoTestHelper.cpp",
"com_android_server_HardwarePropertiesManagerService.cpp",
@@ -54,6 +53,7 @@ cc_library_static {
"com_android_server_am_LowMemDetector.cpp",
"onload.cpp",
":lib_networkStatsFactory_native",
+ ":tethering-jni-srcs",
],
include_dirs: [
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index 8ddb86b08ea3..51bea1f068ad 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -154,21 +154,29 @@ class VibratorShim : public V1_4::IVibrator {
sp<aidl::IVibratorCallback> cb = callback ? new CallbackShim(callback) : nullptr;
int timeoutMs = 0;
- V1_0::Status status = toHidlStatus(
+ Return<V1_0::Status> status = toHidlStatus(
mVib->perform(static_cast<aidl::Effect>(effect),
static_cast<aidl::EffectStrength>(strength), cb, &timeoutMs));
- _hidl_cb(status, timeoutMs);
- return android::hardware::Status::ok();
+
+ if (status.isOk()) {
+ _hidl_cb(status, timeoutMs);
+ return android::hardware::Status::ok();
+ } else {
+ return android::hardware::details::StatusOf<V1_0::Status, void>(status);
+ }
}
private:
sp<aidl::IVibrator> mVib;
- V1_0::Status toHidlStatus(const android::binder::Status& status) {
+ Return<V1_0::Status> toHidlStatus(const android::binder::Status& status) {
switch(status.exceptionCode()) {
using android::hardware::Status;
case Status::EX_NONE: return V1_0::Status::OK;
case Status::EX_ILLEGAL_ARGUMENT: return V1_0::Status::BAD_VALUE;
case Status::EX_UNSUPPORTED_OPERATION: return V1_0::Status::UNSUPPORTED_OPERATION;
+ case Status::EX_TRANSACTION_FAILED: {
+ return Status::fromStatusT(status.transactionError());
+ }
}
return V1_0::Status::UNKNOWN_ERROR;
}
@@ -247,8 +255,14 @@ class HalWrapper {
}
ALOGE("Failed to issue command to vibrator HAL. Retrying.");
+
// Restoring connection to the HAL.
- mHal = I::tryGetService();
+ sp<aidl::IVibrator> aidlVib = checkVintfService<aidl::IVibrator>();
+ if (aidlVib) {
+ mHal = new VibratorShim(aidlVib);
+ } else {
+ mHal = I::tryGetService();
+ }
}
return ret;
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2009dbdca448..ef9e69df01df 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -439,7 +439,7 @@ public final class SystemServer {
// In case the runtime switched since last boot (such as when
// the old runtime was removed in an OTA), set the system
- // property so that it is in sync. We can | xq oqi't do this in
+ // property so that it is in sync. We can't do this in
// libnativehelper's JniInvocation::Init code where we already
// had to fallback to a different runtime because it is
// running as root and we need to be the system user to set
diff --git a/services/net/Android.bp b/services/net/Android.bp
index e24dec562a46..c56ecd6e19e7 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -29,6 +29,7 @@ filegroup {
"java/android/net/ConnectivityModuleConnector.java",
"java/android/net/NetworkStackClient.java",
"java/android/net/ip/InterfaceController.java",
+ "java/android/net/netlink/*.java",
"java/android/net/util/InterfaceParams.java",
"java/android/net/util/NetdService.java",
"java/android/net/util/NetworkConstants.java",
diff --git a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
index 485f436f7f65..556f96ace5d2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
@@ -24,6 +24,7 @@ import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow;
@@ -35,6 +36,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.AlarmManagerService.ACTIVE_INDEX;
import static com.android.server.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED;
import static com.android.server.AlarmManagerService.AlarmHandler.CHARGING_STATUS_CHANGED;
+import static com.android.server.AlarmManagerService.AlarmHandler.REMOVE_FOR_CANCELED;
import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_LONG_TIME;
import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_SHORT_TIME;
import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
@@ -80,9 +82,9 @@ import android.provider.Settings;
import android.util.Log;
import android.util.SparseArray;
-import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.dx.mockito.inline.extended.MockedVoidMethod;
import com.android.internal.annotations.GuardedBy;
import com.android.server.usage.AppStandbyInternal;
@@ -171,7 +173,6 @@ public class AlarmManagerServiceTest {
}
public class Injector extends AlarmManagerService.Injector {
- boolean mIsAutomotiveOverride;
Injector(Context context) {
super(context);
@@ -257,12 +258,13 @@ public class AlarmManagerServiceTest {
.startMocking();
doReturn(mIActivityManager).when(ActivityManager::getService);
doReturn(mAppStateTracker).when(() -> LocalServices.getService(AppStateTracker.class));
- doReturn(null)
- .when(() -> LocalServices.getService(DeviceIdleInternal.class));
doReturn(mAppStandbyInternal).when(
() -> LocalServices.getService(AppStandbyInternal.class));
doReturn(mUsageStatsManagerInternal).when(
() -> LocalServices.getService(UsageStatsManagerInternal.class));
+ doCallRealMethod().when((MockedVoidMethod) () ->
+ LocalServices.addService(eq(AlarmManagerInternal.class), any()));
+ doCallRealMethod().when(() -> LocalServices.getService(AlarmManagerInternal.class));
when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong()))
.thenReturn(STANDBY_BUCKET_ACTIVE);
@@ -455,7 +457,6 @@ public class AlarmManagerServiceTest {
assertEquals(expectedTriggerTime, mTestTimer.getElapsed());
}
- @FlakyTest(bugId = 130313408)
@Test
public void testEarliestAlarmSet() {
final PendingIntent pi6 = getNewMockPendingIntent();
@@ -600,11 +601,15 @@ public class AlarmManagerServiceTest {
anyLong())).thenReturn(bucket);
mAppStandbyListener.onAppIdleStateChanged(TEST_CALLING_PACKAGE,
UserHandle.getUserId(TEST_CALLING_UID), false, bucket, 0);
+ assertAndHandleMessageSync(APP_STANDBY_BUCKET_CHANGED);
+ }
+
+ private void assertAndHandleMessageSync(int what) {
final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
verify(mService.mHandler, atLeastOnce()).sendMessage(messageCaptor.capture());
final Message lastMessage = messageCaptor.getValue();
assertEquals("Unexpected message send to handler", lastMessage.what,
- APP_STANDBY_BUCKET_CHANGED);
+ what);
mService.mHandler.handleMessage(lastMessage);
}
@@ -664,12 +669,7 @@ public class AlarmManagerServiceTest {
mChargingReceiver.onReceive(mMockContext,
new Intent(parole ? BatteryManager.ACTION_CHARGING
: BatteryManager.ACTION_DISCHARGING));
- final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
- verify(mService.mHandler, atLeastOnce()).sendMessage(messageCaptor.capture());
- final Message lastMessage = messageCaptor.getValue();
- assertEquals("Unexpected message send to handler", lastMessage.what,
- CHARGING_STATUS_CHANGED);
- mService.mHandler.handleMessage(lastMessage);
+ assertAndHandleMessageSync(CHARGING_STATUS_CHANGED);
}
@Test
@@ -971,12 +971,13 @@ public class AlarmManagerServiceTest {
}
@Test
- public void alarmCountOnPendingIntentCancel() {
+ public void alarmCountOnRemoveForCanceled() {
+ final AlarmManagerInternal ami = LocalServices.getService(AlarmManagerInternal.class);
final PendingIntent pi = getNewMockPendingIntent();
- setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 123, pi);
- verify(pi).registerCancelListener(mService.mOperationCancelListener);
+ setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 12345, pi);
assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
- mService.mOperationCancelListener.onCancelled(pi);
+ ami.remove(pi);
+ assertAndHandleMessageSync(REMOVE_FOR_CANCELED);
assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
}
@@ -985,5 +986,6 @@ public class AlarmManagerServiceTest {
if (mMockingSession != null) {
mMockingSession.finishMocking();
}
+ LocalServices.removeServiceForTest(AlarmManagerInternal.class);
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
new file mode 100644
index 000000000000..3975f0baa22a
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.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.am;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
+import android.app.AppGlobals;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.content.pm.IPackageManager;
+import android.os.Looper;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.AlarmManagerInternal;
+import com.android.server.LocalServices;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+@RunWith(AndroidJUnit4.class)
+public class PendingIntentControllerTest {
+ private static final String TEST_PACKAGE_NAME = "test-package-1";
+ private static final int TEST_CALLING_UID = android.os.Process.myUid();
+ private static final Intent[] TEST_INTENTS = new Intent[]{new Intent("com.test.intent")};
+
+ @Mock
+ private UserController mUserController;
+ @Mock
+ private AlarmManagerInternal mAlarmManagerInternal;
+ @Mock
+ private ActivityManagerInternal mActivityManagerInternal;
+ @Mock
+ private IPackageManager mIPackageManager;
+
+ private MockitoSession mMockingSession;
+ private PendingIntentController mPendingIntentController;
+
+ @Before
+ public void setUp() throws Exception {
+ mMockingSession = mockitoSession()
+ .initMocks(this)
+ .mockStatic(LocalServices.class)
+ .mockStatic(AppGlobals.class)
+ .strictness(Strictness.LENIENT) // Needed to stub LocalServices.getService twice
+ .startMocking();
+ doReturn(mAlarmManagerInternal).when(
+ () -> LocalServices.getService(AlarmManagerInternal.class));
+ doReturn(mActivityManagerInternal).when(
+ () -> LocalServices.getService(ActivityManagerInternal.class));
+ doReturn(mIPackageManager).when(() -> AppGlobals.getPackageManager());
+ when(mIPackageManager.getPackageUid(eq(TEST_PACKAGE_NAME), anyInt(), anyInt())).thenReturn(
+ TEST_CALLING_UID);
+ mPendingIntentController = new PendingIntentController(Looper.getMainLooper(),
+ mUserController);
+ mPendingIntentController.onActivityManagerInternalAdded();
+ }
+
+ private PendingIntentRecord createPendingIntentRecord(int flags) {
+ return mPendingIntentController.getIntentSender(ActivityManager.INTENT_SENDER_BROADCAST,
+ TEST_PACKAGE_NAME, TEST_CALLING_UID, 0, null, null, 0, TEST_INTENTS, null, flags,
+ null);
+ }
+
+ @Test
+ public void alarmsRemovedOnCancel() {
+ final PendingIntentRecord pir = createPendingIntentRecord(0);
+ mPendingIntentController.cancelIntentSender(pir);
+ final ArgumentCaptor<PendingIntent> piCaptor = ArgumentCaptor.forClass(PendingIntent.class);
+ verify(mAlarmManagerInternal).remove(piCaptor.capture());
+ assertEquals("Wrong target for pending intent passed to alarm manager", pir,
+ piCaptor.getValue().getTarget());
+ }
+
+ @Test
+ public void alarmsRemovedOnRecreateWithCancelCurrent() {
+ final PendingIntentRecord pir = createPendingIntentRecord(0);
+ createPendingIntentRecord(PendingIntent.FLAG_CANCEL_CURRENT);
+ final ArgumentCaptor<PendingIntent> piCaptor = ArgumentCaptor.forClass(PendingIntent.class);
+ verify(mAlarmManagerInternal).remove(piCaptor.capture());
+ assertEquals("Wrong target for pending intent passed to alarm manager", pir,
+ piCaptor.getValue().getTarget());
+ }
+
+ @Test
+ public void alarmsRemovedOnSendingOneShot() {
+ final PendingIntentRecord pir = createPendingIntentRecord(PendingIntent.FLAG_ONE_SHOT);
+ pir.send(0, null, null, null, null, null, null);
+ final ArgumentCaptor<PendingIntent> piCaptor = ArgumentCaptor.forClass(PendingIntent.class);
+ verify(mAlarmManagerInternal).remove(piCaptor.capture());
+ assertEquals("Wrong target for pending intent passed to alarm manager", pir,
+ piCaptor.getValue().getTarget());
+ }
+
+ @After
+ public void tearDown() {
+ if (mMockingSession != null) {
+ mMockingSession.finishMocking();
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
index 184dc3dfed62..a47a5671ccb3 100644
--- a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
@@ -16,6 +16,8 @@
package com.android.server.attention;
+import static com.android.server.attention.AttentionManagerService.ATTENTION_CACHE_BUFFER_SIZE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -39,6 +41,8 @@ import android.service.attention.IAttentionService;
import androidx.test.filters.SmallTest;
import com.android.server.attention.AttentionManagerService.AttentionCheck;
+import com.android.server.attention.AttentionManagerService.AttentionCheckCache;
+import com.android.server.attention.AttentionManagerService.AttentionCheckCacheBuffer;
import com.android.server.attention.AttentionManagerService.AttentionHandler;
import com.android.server.attention.AttentionManagerService.UserState;
@@ -56,11 +60,16 @@ public class AttentionManagerServiceTest {
private AttentionManagerService mSpyAttentionManager;
private UserState mSpyUserState;
private final int mTimeout = 1000;
- @Mock private AttentionCallbackInternal mMockAttentionCallbackInternal;
- @Mock private AttentionHandler mMockHandler;
- @Mock private IAttentionCallback mMockIAttentionCallback;
- @Mock private IPowerManager mMockIPowerManager;
- @Mock Context mContext;
+ @Mock
+ private AttentionCallbackInternal mMockAttentionCallbackInternal;
+ @Mock
+ private AttentionHandler mMockHandler;
+ @Mock
+ private IAttentionCallback mMockIAttentionCallback;
+ @Mock
+ private IPowerManager mMockIPowerManager;
+ @Mock
+ Context mContext;
@Before
public void setUp() throws RemoteException {
@@ -140,12 +149,45 @@ public class AttentionManagerServiceTest {
mSpyAttentionManager.onSwitchUser(userId);
}
+ @Test
+ public void testAttentionCheckCacheBuffer_getLast_returnTheLastElement() {
+ AttentionCheckCacheBuffer buffer = new AttentionCheckCacheBuffer();
+ buffer.add(new AttentionCheckCache(0, 0, 1L));
+ AttentionCheckCache cache = new AttentionCheckCache(0, 0, 2L);
+ buffer.add(cache);
+ assertThat(buffer.getLast()).isEqualTo(cache);
+ }
+
+ @Test
+ public void testAttentionCheckCacheBuffer_get_returnNullWhenOutOfBoundary() {
+ AttentionCheckCacheBuffer buffer = new AttentionCheckCacheBuffer();
+ assertThat(buffer.get(1)).isNull();
+ }
+
+ @Test
+ public void testAttentionCheckCacheBuffer_get_handleCircularIndexing() {
+ AttentionCheckCacheBuffer buffer = new AttentionCheckCacheBuffer();
+ AttentionCheckCache cache = new AttentionCheckCache(0L, 0, 1L);
+ // Insert SIZE+1 elements.
+ for (int i = 0; i <= ATTENTION_CACHE_BUFFER_SIZE; i++) {
+ if (i == 1) {
+ buffer.add(cache);
+ } else {
+ buffer.add(new AttentionCheckCache(0L, 0, i));
+ }
+ }
+ // The element that was at index 1 should be at index 0 after inserting SIZE + 1 elements.
+ assertThat(buffer.get(0)).isEqualTo(cache);
+ }
+
private class MockIAttentionService implements IAttentionService {
public void checkAttention(IAttentionCallback callback) throws RemoteException {
callback.onSuccess(0, 0);
}
+
public void cancelAttentionCheck(IAttentionCallback callback) {
}
+
public IBinder asBinder() {
return null;
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java
index fa90b291eeee..0d44318e4aaa 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationShellCmdTest.java
@@ -116,8 +116,8 @@ public class NotificationShellCmdTest extends UiServiceTestCase {
ArgumentCaptor<Notification> notificationCaptor =
ArgumentCaptor.forClass(Notification.class);
verify(mMockBinderService).enqueueNotificationWithTag(
- eq(NotificationShellCmd.NOTIFICATION_PACKAGE),
- eq("android"),
+ eq(getContext().getPackageName()),
+ eq(getContext().getPackageName()),
eq(aTag),
eq(NotificationShellCmd.NOTIFICATION_ID),
notificationCaptor.capture(),
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index 7c867b695203..44cacd821355 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -195,9 +195,15 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
public void testOnReportFullyDrawn() {
onActivityLaunched();
+ // The activity reports fully drawn before windows drawn, then the fully drawn event will
+ // be pending (see {@link WindowingModeTransitionInfo#pendingFullyDrawn}).
mActivityMetricsLogger.logAppTransitionReportedDrawn(mTopActivity, false);
+ notifyTransitionStarting();
+ // The pending fully drawn event should send when the actual windows drawn event occurs.
+ notifyWindowsDrawn(mTopActivity);
verifyAsync(mLaunchObserver).onReportFullyDrawn(eqProto(mTopActivity), anyLong());
+ verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mTopActivity), anyLong());
verifyNoMoreInteractions(mLaunchObserver);
}
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 38d6c9c1e4db..2ce37f1be4c5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -53,8 +53,6 @@ import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStack.ActivityState.STARTED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
-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;
@@ -136,13 +134,13 @@ public class ActivityRecordTests extends ActivityTestsBase {
@Test
public void testStackCleanupOnActivityRemoval() {
- mTask.mTask.removeChild(mActivity);
+ mTask.removeChild(mActivity);
verify(mStack, times(1)).onActivityRemovedFromStack(any());
}
@Test
public void testStackCleanupOnTaskRemoval() {
- mStack.removeTask(mTask, null /*reason*/, REMOVE_TASK_MODE_MOVING);
+ mStack.removeChild(mTask, null /*reason*/);
// Stack should be gone on task removal.
assertNull(mService.mRootActivityContainer.getStack(mStack.mStackId));
}
@@ -325,7 +323,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
: ORIENTATION_PORTRAIT;
mTask.onRequestedOverrideConfigurationChanged(newConfig);
- doReturn(true).when(mTask.mTask).isDragResizing();
+ doReturn(true).when(mTask).isDragResizing();
mActivity.mRelaunchReason = ActivityTaskManagerService.RELAUNCH_REASON_NONE;
@@ -382,7 +380,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
}
// Mimic the behavior that display doesn't handle app's requested orientation.
- final DisplayContent dc = mTask.mTask.getDisplayContent();
+ final DisplayContent dc = mTask.getDisplayContent();
doReturn(false).when(dc).onDescendantOrientationChanged(any(), any());
doReturn(false).when(dc).handlesOrientationChangeFromDescendant();
@@ -1174,7 +1172,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
// Empty the home stack.
final ActivityStack homeStack = mActivity.getDisplay().getHomeStack();
for (TaskRecord t : homeStack.getAllTasks()) {
- homeStack.removeTask(t, "test", REMOVE_TASK_MODE_DESTROYING);
+ homeStack.removeChild(t, "test");
}
mActivity.finishing = true;
doReturn(false).when(mRootActivityContainer).resumeFocusedStacksTopActivities();
@@ -1200,7 +1198,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
// Empty the home stack.
final ActivityStack homeStack = mActivity.getDisplay().getHomeStack();
for (TaskRecord t : homeStack.getAllTasks()) {
- homeStack.removeTask(t, "test", REMOVE_TASK_MODE_DESTROYING);
+ homeStack.removeChild(t, "test");
}
mActivity.finishing = true;
spyOn(mStack);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index fcebb81fd658..cc0cc3f85d50 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -38,7 +38,6 @@ import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
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;
@@ -93,21 +92,6 @@ public class ActivityStackTests extends ActivityTestsBase {
}
@Test
- public void testEmptyTaskCleanupOnRemove() {
- assertNotNull(mTask.getTask());
- mStack.removeTask(mTask, "testEmptyTaskCleanupOnRemove", REMOVE_TASK_MODE_DESTROYING);
- assertNull(mTask.getTask());
- }
-
- @Test
- public void testOccupiedTaskCleanupOnRemove() {
- final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
- assertNotNull(mTask.getTask());
- mStack.removeTask(mTask, "testOccupiedTaskCleanupOnRemove", REMOVE_TASK_MODE_DESTROYING);
- assertNotNull(mTask.getTask());
- }
-
- @Test
public void testResumedActivity() {
final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
assertNull(mStack.getResumedActivity());
@@ -996,27 +980,6 @@ public class ActivityStackTests extends ActivityTestsBase {
}
@Test
- public void testAdjustFocusedStackToHomeWhenNoActivity() {
- final ActivityStack homeStask = mDefaultDisplay.getHomeStack();
- TaskRecord homeTask = homeStask.topTask();
- if (homeTask == null) {
- // Create home task if there isn't one.
- homeTask = new TaskBuilder(mSupervisor).setStack(homeStask).build();
- }
-
- final ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
- mStack.moveToFront("testAdjustFocusedStack");
-
- // Simulate that home activity has not been started or is force-stopped.
- homeStask.removeTask(homeTask, "testAdjustFocusedStack", REMOVE_TASK_MODE_DESTROYING);
-
- // Finish the only activity.
- topActivity.finishIfPossible("testAdjustFocusedStack", false /* oomAdj */);
- // Although home stack is empty, it should still be the focused stack.
- assertEquals(homeStask, mDefaultDisplay.getFocusedStack());
- }
-
- @Test
public void testWontFinishHomeStackImmediately() {
final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index ace5d4efa39b..a28bbb60d70c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -715,7 +715,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
if (startedActivity != null && startedActivity.getTaskRecord() != null) {
// Remove the activity so it doesn't interfere with with subsequent activity launch
// tests from this method.
- startedActivity.getTaskRecord().mTask.removeChild(startedActivity);
+ startedActivity.getTaskRecord().removeChild(startedActivity);
}
}
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 78db6c92772f..1db8f1b1b596 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -269,7 +269,7 @@ class ActivityTestsBase extends SystemServiceTestsBase {
// fullscreen value is normally read from resources in ctor, so for testing we need
// to set it somewhere else since we can't mock resources.
doReturn(true).when(activity).occludesParent();
- activity.setTask(mTaskRecord);
+ mTaskRecord.addChild(activity);
// Make visible by default...
activity.setHidden(false);
}
@@ -376,15 +376,13 @@ class ActivityTestsBase extends SystemServiceTestsBase {
final TaskRecord task = new TaskRecord(mSupervisor.mService, mTaskId, aInfo,
intent /*intent*/, mVoiceSession, null /*_voiceInteractor*/,
- null /*taskDescription*/);
+ null /*taskDescription*/, mStack);
spyOn(task);
task.mUserId = mUserId;
if (mStack != null) {
mStack.moveToFront("test");
- mStack.addTask(task, true, "creating test task");
- task.createTask(true, true);
- spyOn(task.mTask);
+ mStack.addChild(task, true, true);
}
return task;
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index 1fb6a563aa40..7b9be3d2746b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -62,7 +62,7 @@ public class AppChangeTransitionTests extends WindowTestsBase {
public void setUpOnDisplay(DisplayContent dc) {
mActivity = createTestActivityRecord(dc, WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD);
mTask = mActivity.getTask();
- mStack = mTask.mStack;
+ mStack = mTask.getTaskStack();
// Set a remote animator with snapshot disabled. Snapshots don't work in wmtests.
RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
@@ -165,7 +165,7 @@ public class AppChangeTransitionTests extends WindowTestsBase {
// setup currently defaults to no snapshot.
setUpOnDisplay(mDisplayContent);
- mTask.mTaskRecord.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
assertEquals(1, mDisplayContent.mChangingApps.size());
assertTrue(mActivity.isInChangeTransition());
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 2f0486d3e81b..d33dbd1dda7c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -48,7 +48,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import android.content.res.Configuration;
@@ -63,7 +63,6 @@ import androidx.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mockito;
/**
* Tests for the {@link ActivityRecord} class.
@@ -209,9 +208,11 @@ public class AppWindowTokenTests extends WindowTestsBase {
@Test
public void testSizeCompatBounds() {
+ // TODO(task-merge): Move once Task is merged into TaskRecord
+ final TaskRecord tr = (TaskRecord) mTask;
// Disable the real configuration resolving because we only simulate partial flow.
// TODO: Have test use full flow.
- doNothing().when(mTask.mTaskRecord).computeConfigResourceOverrides(any(), any());
+ doNothing().when(tr).computeConfigResourceOverrides(any(), any());
final Rect fixedBounds = mActivity.getRequestedOverrideConfiguration().windowConfiguration
.getBounds();
fixedBounds.set(0, 0, 1200, 1600);
@@ -337,11 +338,9 @@ public class AppWindowTokenTests extends WindowTestsBase {
mDisplayContent.getDisplayRotation().setFixedToUserRotation(
DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
-
- mTask.mTaskRecord = Mockito.mock(TaskRecord.class, RETURNS_DEEP_STUBS);
+ reset(mTask);
mActivity.reportDescendantOrientationChangeIfNeeded();
-
- verify(mTask.mTaskRecord).onConfigurationChanged(any(Configuration.class));
+ verify(mTask).onConfigurationChanged(any(Configuration.class));
}
@Test
@@ -451,6 +450,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
@Test
public void testTransitionAnimationBounds() {
+ removeGlobalMinSizeRestriction();
final Rect stackBounds = new Rect(0, 0, 1000, 600);
final Rect taskBounds = new Rect(100, 400, 600, 800);
mStack.setBounds(stackBounds);
@@ -458,16 +458,16 @@ public class AppWindowTokenTests extends WindowTestsBase {
// Check that anim bounds for freeform window match task bounds
mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
- assertEquals(taskBounds, mActivity.getAnimationBounds(STACK_CLIP_NONE));
+ assertEquals(mTask.getBounds(), mActivity.getAnimationBounds(STACK_CLIP_NONE));
// STACK_CLIP_AFTER_ANIM should use task bounds since they will be clipped by
// bounds animation layer.
mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- assertEquals(taskBounds, mActivity.getAnimationBounds(STACK_CLIP_AFTER_ANIM));
+ assertEquals(mTask.getBounds(), mActivity.getAnimationBounds(STACK_CLIP_AFTER_ANIM));
// STACK_CLIP_BEFORE_ANIM should use stack bounds since it won't be clipped later.
mTask.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
- assertEquals(stackBounds, mActivity.getAnimationBounds(STACK_CLIP_BEFORE_ANIM));
+ assertEquals(mStack.getBounds(), mActivity.getAnimationBounds(STACK_CLIP_BEFORE_ANIM));
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 01489c6c8c1b..bd137fb573e2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -119,7 +119,7 @@ public class DisplayContentTests extends WindowTestsBase {
waitUntilHandlersIdle();
exitingApp.mIsExiting = true;
- exitingApp.getTask().mStack.mExitingActivities.add(exitingApp);
+ exitingApp.getTask().getTaskStack().mExitingActivities.add(exitingApp);
assertForAllWindowsOrder(Arrays.asList(
mWallpaperWindow,
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index 8c2ae5a7659a..55947ae9626f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -178,11 +178,14 @@ public class InsetsPolicyTest extends WindowTestsBase {
@Test
public void testShowTransientBars_topCanBeTransient_appGetsTopFakeControl() {
+ // Adding app window before setting source visibility is to prevent the visibility from
+ // being cleared by InsetsSourceProvider.updateVisibility.
+ final WindowState app = addWindow(TYPE_APPLICATION, "app");
+
addWindow(TYPE_STATUS_BAR, "topBar")
.getControllableInsetProvider().getSource().setVisible(false);
addWindow(TYPE_NAVIGATION_BAR, "navBar")
.getControllableInsetProvider().getSource().setVisible(true);
- final WindowState app = addWindow(TYPE_APPLICATION, "app");
final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
policy.updateBarControlTarget(app);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index cc598ffa63bd..69091c61ec90 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -885,7 +885,7 @@ public class RecentTasksTest extends ActivityTestsBase {
final int taskId = task.mTaskId;
mRecentTasks.add(task);
// Only keep the task in RecentTasks.
- task.removeWindowContainer();
+ task.removeIfPossible();
mStack.remove();
// The following APIs should not restore task from recents to the active list.
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index 839ddb2038ff..ca8f5351c73a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -196,9 +196,6 @@ public class RecentsAnimationTest extends ActivityTestsBase {
doReturn(app).when(mService).getProcessController(eq(recentActivity.processName), anyInt());
ClientLifecycleManager lifecycleManager = mService.getLifecycleManager();
doNothing().when(lifecycleManager).scheduleTransaction(any());
- AppWarnings appWarnings = mService.getAppWarningsLocked();
- spyOn(appWarnings);
- doNothing().when(appWarnings).onStartActivity(any());
startRecentsActivity();
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index aa97de72e507..63f70c05f203 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -36,7 +36,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
@@ -272,8 +271,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
assertTrue(pinnedActivity.isFocusable());
// Without the overridding activity, stack should not be focusable.
- pinnedStack.removeTask(pinnedActivity.getTaskRecord(), "testFocusability",
- REMOVE_TASK_MODE_DESTROYING);
+ pinnedStack.removeChild(pinnedActivity.getTaskRecord(), "testFocusability");
assertFalse(pinnedStack.isFocusable());
}
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 fa1f435a37c0..ad1d1afe7603 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -437,6 +437,10 @@ public class SystemServicesTestRule implements TestRule {
spyOn(getLockTaskController());
spyOn(getTaskChangeNotificationController());
initRootActivityContainerMocks();
+
+ AppWarnings appWarnings = getAppWarningsLocked();
+ spyOn(appWarnings);
+ doNothing().when(appWarnings).onStartActivity(any());
}
void initRootActivityContainerMocks() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
index df55b39b0817..9275512bc719 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
@@ -66,7 +66,6 @@ public class TaskPositionerTests extends WindowTestsBase {
private int mMinVisibleWidth;
private int mMinVisibleHeight;
private TaskPositioner mPositioner;
- private WindowState mWindow;
@Before
public void setUp() {
@@ -79,18 +78,18 @@ public class TaskPositionerTests extends WindowTestsBase {
// This should be the same calculation as the TaskPositioner uses.
mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, dm);
mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, dm);
+ removeGlobalMinSizeRestriction();
- mPositioner = new TaskPositioner(mWm, mock(IActivityTaskManager.class));
- mPositioner.register(mDisplayContent);
+ WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "window");
+ mPositioner = new TaskPositioner(mWm, mWm.mAtmService);
- mWindow = createWindow(null, TYPE_BASE_APPLICATION, "window");
- mPositioner.mTask = mWindow.getTask();
- mWindow.getStack().setWindowingMode(WINDOWING_MODE_FREEFORM);
+ mPositioner.register(mDisplayContent, win);
+
+ win.getStack().setWindowingMode(WINDOWING_MODE_FREEFORM);
}
@After
public void tearDown() {
- mWindow = null;
mPositioner = null;
}
@@ -121,8 +120,8 @@ public class TaskPositionerTests extends WindowTestsBase {
mPositioner.mTask.setBounds(r, true);
// Start a drag resize starting upper left.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */,
+ r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
assertBoundsEquals(r, mPositioner.getWindowDragBounds());
// Drag to a good landscape size.
@@ -148,8 +147,8 @@ public class TaskPositionerTests extends WindowTestsBase {
mPositioner.getWindowDragBounds());
// Start a drag resize left and see that only the left coord changes..
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, r.left - MOUSE_DELTA_X, midY);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */,
+ r.left - MOUSE_DELTA_X, midY);
// Drag to the left.
mPositioner.resizeDrag(0.0f, midY);
@@ -183,8 +182,8 @@ public class TaskPositionerTests extends WindowTestsBase {
mPositioner.mTask.setBounds(r, true);
// Drag upper left.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */,
+ r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
mPositioner.resizeDrag(0.0f, 0.0f);
assertNotEquals(r.left, mPositioner.getWindowDragBounds().left);
assertEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -192,8 +191,8 @@ public class TaskPositionerTests extends WindowTestsBase {
assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag upper.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, midX, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */, midX,
+ r.top - MOUSE_DELTA_Y);
mPositioner.resizeDrag(0.0f, 0.0f);
assertEquals(r.left, mPositioner.getWindowDragBounds().left);
assertEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -201,8 +200,8 @@ public class TaskPositionerTests extends WindowTestsBase {
assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag upper right.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, r.right + MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */,
+ r.right + MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
mPositioner.resizeDrag(r.right + 100, 0.0f);
assertEquals(r.left, mPositioner.getWindowDragBounds().left);
assertNotEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -210,8 +209,8 @@ public class TaskPositionerTests extends WindowTestsBase {
assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag right.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, r.right + MOUSE_DELTA_X, midY);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */,
+ r.right + MOUSE_DELTA_X, midY);
mPositioner.resizeDrag(r.right + 100, 0.0f);
assertEquals(r.left, mPositioner.getWindowDragBounds().left);
assertNotEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -219,8 +218,7 @@ public class TaskPositionerTests extends WindowTestsBase {
assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag bottom right.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */,
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */,
r.right + MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y);
mPositioner.resizeDrag(r.right + 100, r.bottom + 100);
assertEquals(r.left, mPositioner.getWindowDragBounds().left);
@@ -229,8 +227,8 @@ public class TaskPositionerTests extends WindowTestsBase {
assertNotEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag bottom.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, midX, r.bottom + MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */, midX,
+ r.bottom + MOUSE_DELTA_Y);
mPositioner.resizeDrag(r.right + 100, r.bottom + 100);
assertEquals(r.left, mPositioner.getWindowDragBounds().left);
assertEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -238,8 +236,8 @@ public class TaskPositionerTests extends WindowTestsBase {
assertNotEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag bottom left.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, r.left - MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */,
+ r.left - MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y);
mPositioner.resizeDrag(0.0f, r.bottom + 100);
assertNotEquals(r.left, mPositioner.getWindowDragBounds().left);
assertEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -247,8 +245,8 @@ public class TaskPositionerTests extends WindowTestsBase {
assertNotEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag left.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, r.left - MOUSE_DELTA_X, midY);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */,
+ r.left - MOUSE_DELTA_X, midY);
mPositioner.resizeDrag(0.0f, r.bottom + 100);
assertNotEquals(r.left, mPositioner.getWindowDragBounds().left);
assertEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -265,8 +263,8 @@ public class TaskPositionerTests extends WindowTestsBase {
final Rect r = new Rect(100, 220, 700, 520);
mPositioner.mTask.setBounds(r, true);
- mPositioner.startDrag(mWindow, true /* resizing */,
- true /* preserveOrientation */, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /* resizing */, true /* preserveOrientation */,
+ r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
assertBoundsEquals(r, mPositioner.getWindowDragBounds());
// Drag to a good landscape size.
@@ -304,8 +302,8 @@ public class TaskPositionerTests extends WindowTestsBase {
final int midY = (r.top + r.bottom) / 2;
mPositioner.mTask.setBounds(r, true);
- mPositioner.startDrag(mWindow, true /* resizing */,
- true /* preserveOrientation */, r.left - MOUSE_DELTA_X, midY);
+ mPositioner.startDrag(true /* resizing */, true /* preserveOrientation */,
+ r.left - MOUSE_DELTA_X, midY);
// Drag to the left.
mPositioner.resizeDrag(0.0f, midY);
@@ -345,8 +343,8 @@ public class TaskPositionerTests extends WindowTestsBase {
final int midX = (r.left + r.right) / 2;
mPositioner.mTask.setBounds(r, true);
- mPositioner.startDrag(mWindow, true /*resizing*/,
- true /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /*resizing*/, true /*preserveOrientation*/, midX,
+ r.top - MOUSE_DELTA_Y);
// Drag to the left (no change).
mPositioner.resizeDrag(0.0f, r.top);
@@ -381,8 +379,8 @@ public class TaskPositionerTests extends WindowTestsBase {
final Rect r = new Rect(330, 100, 630, 600);
mPositioner.mTask.setBounds(r, true);
- mPositioner.startDrag(mWindow, true /*resizing*/,
- true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /*resizing*/, true /*preserveOrientation*/,
+ r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
assertBoundsEquals(r, mPositioner.getWindowDragBounds());
// Drag to a good landscape size.
@@ -415,8 +413,8 @@ public class TaskPositionerTests extends WindowTestsBase {
final int midY = (r.top + r.bottom) / 2;
mPositioner.mTask.setBounds(r, true);
- mPositioner.startDrag(mWindow, true /* resizing */,
- true /* preserveOrientation */, r.left - MOUSE_DELTA_X, midY);
+ mPositioner.startDrag(true /* resizing */, true /* preserveOrientation */,
+ r.left - MOUSE_DELTA_X, midY);
// Drag to the left.
mPositioner.resizeDrag(0.0f, midY);
@@ -458,8 +456,8 @@ public class TaskPositionerTests extends WindowTestsBase {
final int midX = (r.left + r.right) / 2;
mPositioner.mTask.setBounds(r, true);
- mPositioner.startDrag(mWindow, true /* resizing */,
- true /* preserveOrientation */, midX, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /* resizing */, true /* preserveOrientation */, midX,
+ r.top - MOUSE_DELTA_Y);
// Drag to the left (no change).
mPositioner.resizeDrag(0.0f, r.top);
@@ -493,10 +491,7 @@ public class TaskPositionerTests extends WindowTestsBase {
+ ") " + Log.getStackTraceString(new Throwable()));
}
}
- assertEquals("left", expected.left, actual.left);
- assertEquals("right", expected.right, actual.right);
- assertEquals("top", expected.top, actual.top);
- assertEquals("bottom", expected.bottom, actual.bottom);
+ assertEquals(expected, actual);
}
@FlakyTest(bugId = 129492888)
@@ -504,7 +499,7 @@ public class TaskPositionerTests extends WindowTestsBase {
public void testFinishingMovingWhenBinderDied() {
spyOn(mWm.mTaskPositioningController);
- mPositioner.startDrag(mWindow, false, false, 0 /* startX */, 0 /* startY */);
+ mPositioner.startDrag(false, false, 0 /* startX */, 0 /* startY */);
verify(mWm.mTaskPositioningController, never()).finishTaskPositioning();
mPositioner.binderDied();
verify(mWm.mTaskPositioningController).finishTaskPositioning();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
index f8d49ad18664..d2342f081fa1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
@@ -66,7 +66,8 @@ public class TaskPositioningControllerTests extends WindowTestsBase {
any(InputChannel.class))).thenReturn(true);
mWindow = createWindow(null, TYPE_BASE_APPLICATION, "window");
- mWindow.getTask().setResizeable(RESIZE_MODE_RESIZEABLE);
+ // TODO(task-merge): Remove cast.
+ ((TaskRecord) mWindow.getTask()).setResizeMode(RESIZE_MODE_RESIZEABLE);
mWindow.mInputChannel = new InputChannel();
mWm.mWindowMap.put(mWindow.mClient.asBinder(), mWindow);
doReturn(mock(InputMonitor.class)).when(mDisplayContent).getInputMonitor();
@@ -142,7 +143,8 @@ public class TaskPositioningControllerTests extends WindowTestsBase {
doReturn(mWindow.getTask()).when(content).findTaskForResizePoint(anyInt(), anyInt());
assertNotNull(mWindow.getTask().getTopVisibleAppMainWindow());
- mWindow.getTask().setResizeable(RESIZE_MODE_UNRESIZEABLE);
+ // TODO(task-merge): Remove cast.
+ ((TaskRecord) mWindow.getTask()).setResizeMode(RESIZE_MODE_UNRESIZEABLE);
mTarget.handleTapOutsideTask(content, 0, 0);
// Wait until the looper processes finishTaskPositioning.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index a4e38f15e0e7..2cafc965e648 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -132,7 +132,7 @@ public class TaskRecordTests extends ActivityTestsBase {
@Test
public void testCopyBaseIntentForTaskInfo() {
final TaskRecord task = createTaskRecord(1);
- task.mTaskDescription = new ActivityManager.TaskDescription();
+ task.setTaskDescription(new ActivityManager.TaskDescription());
final TaskInfo info = task.getTaskInfo();
// The intent of info should be a copy so assert that they are different instances.
@@ -348,10 +348,12 @@ public class TaskRecordTests extends ActivityTestsBase {
TaskRecord task = stack.getChildAt(0);
ActivityRecord root = task.getTopActivity();
- final WindowContainer parentWindowContainer = mock(WindowContainer.class);
- Mockito.doReturn(parentWindowContainer).when(task.mTask).getParent();
- Mockito.doReturn(true).when(parentWindowContainer)
- .handlesOrientationChangeFromDescendant();
+ final WindowContainer parentWindowContainer =
+ new WindowContainer(mSystemServicesTestRule.getWindowManagerService());
+ spyOn(parentWindowContainer);
+ parentWindowContainer.setBounds(fullScreenBounds);
+ doReturn(parentWindowContainer).when(task).getParent();
+ doReturn(true).when(parentWindowContainer).handlesOrientationChangeFromDescendant();
// Setting app to fixed portrait fits within parent, but TaskRecord shouldn't adjust the
// bounds because its parent says it will handle it at a later time.
@@ -433,7 +435,7 @@ public class TaskRecordTests extends ActivityTestsBase {
info.targetActivity = targetClassName;
final TaskRecord task = TaskRecord.create(mService, 1 /* taskId */, info, intent,
- null /* taskDescription */);
+ null /* taskDescription */, null /*stack*/);
assertEquals("The alias activity component should be saved in task intent.", aliasClassName,
task.intent.getComponent().getClassName());
@@ -834,8 +836,9 @@ public class TaskRecordTests extends ActivityTestsBase {
private TaskRecord createTaskRecord(int taskId) {
return new TaskRecord(mService, taskId, new Intent(), null, null, null,
ActivityBuilder.getDefaultComponent(), null, false, false, false, 0, 10050, null,
- new ArrayList<>(), 0, false, null, 0, 0, 0, 0, 0, null, 0, false, false, false, 0,
- 0, null /*ActivityInfo*/, null /*_voiceSession*/, null /*_voiceInteractor*/);
+ 0, false, null, 0, 0, 0, 0, 0, null, 0, false, false, false, 0,
+ 0, null /*ActivityInfo*/, null /*_voiceSession*/, null /*_voiceInteractor*/,
+ null /*stack*/);
}
private static class TestTaskRecordFactory extends TaskRecordFactory {
@@ -843,16 +846,16 @@ public class TaskRecordTests extends ActivityTestsBase {
@Override
TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
- Intent intent,
- IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
+ Intent intent, IVoiceInteractionSession voiceSession,
+ IVoiceInteractor voiceInteractor, ActivityStack stack) {
mCreated = true;
return null;
}
@Override
TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
- Intent intent,
- ActivityManager.TaskDescription taskDescription) {
+ Intent intent, ActivityManager.TaskDescription taskDescription,
+ ActivityStack stack) {
mCreated = true;
return null;
}
@@ -863,14 +866,14 @@ public class TaskRecordTests extends ActivityTestsBase {
ComponentName realActivity,
ComponentName origActivity, boolean rootWasReset, boolean autoRemoveRecents,
boolean askedCompatMode, int userId, int effectiveUid, String lastDescription,
- ArrayList<ActivityRecord> activities, long lastTimeMoved,
+ long lastTimeMoved,
boolean neverRelinquishIdentity,
ActivityManager.TaskDescription lastTaskDescription,
int taskAffiliation, int prevTaskId, int nextTaskId, int taskAffiliationColor,
int callingUid, String callingPackage, int resizeMode,
boolean supportsPictureInPicture,
boolean realActivitySuspended, boolean userSetupComplete, int minWidth,
- int minHeight) {
+ int minHeight, ActivityStack stack) {
mCreated = true;
return null;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
index a66c79ced83c..78970479228c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -121,7 +121,7 @@ public class TaskStackContainersTests extends WindowTestsBase {
false /* includingParents */);
// Move the task of {@code mDisplayContent} to top.
- stack.positionChildAt(WindowContainer.POSITION_TOP, task, true /* includingParents */);
+ stack.positionChildAt(WindowContainer.POSITION_TOP, (TaskRecord) task, true /* includingParents */);
final int indexOfDisplayWithPinnedStack = mWm.mRoot.mChildren.indexOf(mDisplayContent);
assertEquals("The testing DisplayContent should be moved to top with task",
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 164d28d57cb0..a9d0ea11f21f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -58,12 +58,12 @@ public class TaskStackTests extends WindowTestsBase {
final Task task2 = createTaskInStack(stack, 1 /* userId */);
// Current user task should be moved to top.
- stack.positionChildAt(WindowContainer.POSITION_TOP, task1, false /* includingParents */);
+ stack.positionChildAt(WindowContainer.POSITION_TOP, (TaskRecord) task1, false /* includingParents */);
assertEquals(stack.mChildren.get(0), task2);
assertEquals(stack.mChildren.get(1), task1);
// Non-current user won't be moved to top.
- stack.positionChildAt(WindowContainer.POSITION_TOP, task2, false /* includingParents */);
+ stack.positionChildAt(WindowContainer.POSITION_TOP, (TaskRecord) task2, false /* includingParents */);
assertEquals(stack.mChildren.get(0), task2);
assertEquals(stack.mChildren.get(1), task1);
}
@@ -112,12 +112,12 @@ public class TaskStackTests extends WindowTestsBase {
public void testStackRemoveImmediately() {
final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- assertEquals(stack, task.mStack);
+ assertEquals(stack, task.getTaskStack());
// Remove stack and check if its child is also removed.
stack.removeImmediately();
assertNull(stack.getDisplayContent());
- assertNull(task.mStack);
+ assertNull(task.getTaskStack());
}
@Test
@@ -133,7 +133,7 @@ public class TaskStackTests extends WindowTestsBase {
assertEquals(0, stack.getChildCount());
assertNull(stack.getDisplayContent());
assertNull(task.getDisplayContent());
- assertNull(task.mStack);
+ assertNull(task.getTaskStack());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 4dfa26644fa9..cb2e1e03a446 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -92,7 +94,7 @@ public class TaskTests extends WindowTestsBase {
boolean gotException = false;
try {
- task.reparent(stackController1, 0, false/* moveParents */);
+ task.reparent(stackController1, 0, false/* moveParents */, "testReparent");
} catch (IllegalArgumentException e) {
gotException = true;
}
@@ -100,14 +102,14 @@ public class TaskTests extends WindowTestsBase {
gotException = false;
try {
- task.reparent(null, 0, false/* moveParents */);
+ task.reparent(null, 0, false/* moveParents */, "testReparent");
} catch (IllegalArgumentException e) {
gotException = true;
}
assertTrue("Should not be able to reparent to a stack that doesn't exist",
gotException);
- task.reparent(stackController2, 0, false/* moveParents */);
+ task.reparent(stackController2, 0, false/* moveParents */, "testReparent");
assertEquals(stackController2, task.getParent());
assertEquals(0, task.getParent().mChildren.indexOf(task));
assertEquals(1, task2.getParent().mChildren.indexOf(task2));
@@ -125,7 +127,7 @@ public class TaskTests extends WindowTestsBase {
final TaskStack stack2 = createTaskStackOnDisplay(dc);
final Task task2 = createTaskInStack(stack2, 0 /* userId */);
// Reparent and check state
- task.reparent(stack2, 0, false /* moveParents */);
+ task.reparent(stack2, 0, false /* moveParents */, "testReparent_BetweenDisplays");
assertEquals(stack2, task.getParent());
assertEquals(0, task.getParent().mChildren.indexOf(task));
assertEquals(1, task2.getParent().mChildren.indexOf(task2));
@@ -138,6 +140,7 @@ public class TaskTests extends WindowTestsBase {
final Task task = createTaskInStack(stack1, 0 /* userId */);
// Check that setting bounds also updates surface position
+ task.setWindowingMode(WINDOWING_MODE_FREEFORM);
Rect bounds = new Rect(10, 10, 100, 200);
task.setBounds(bounds);
assertEquals(new Point(bounds.left, bounds.top), task.getLastSurfacePosition());
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java
index 8520d212c4ea..b8de3ca4ea1c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java
@@ -37,27 +37,27 @@ import org.junit.runner.RunWith;
* Test class for {@link TaskSnapshotSurface}.
*
* Build/Install/Run:
- * atest FrameworksServicesTest:AppWindowThumbnailTest
+ * atest WmTests:WindowContainerThumbnailTest
*
*/
@SmallTest
@Presubmit
@RunWith(WindowTestRunner.class)
-public class AppWindowThumbnailTest extends WindowTestsBase {
- private AppWindowThumbnail buildThumbnail() {
+public class WindowContainerThumbnailTest extends WindowTestsBase {
+ private WindowContainerThumbnail buildThumbnail() {
final GraphicBuffer buffer = GraphicBuffer.create(1, 1, PixelFormat.RGBA_8888,
GraphicBuffer.USAGE_SW_READ_RARELY | GraphicBuffer.USAGE_SW_WRITE_NEVER);
final ActivityRecord mockAr = mock(ActivityRecord.class);
when(mockAr.getPendingTransaction()).thenReturn(new StubTransaction());
when(mockAr.makeSurface()).thenReturn(new MockSurfaceControlBuilder());
- return new AppWindowThumbnail(new StubTransaction(), mockAr,
+ return new WindowContainerThumbnail(new StubTransaction(), mockAr,
buffer, false, mock(Surface.class), mock(SurfaceAnimator.class));
}
@Test
@FlakyTest(bugId = 131005232)
public void testDestroy_nullsSurface() {
- final AppWindowThumbnail t = buildThumbnail();
+ final WindowContainerThumbnail t = buildThumbnail();
assertNotNull(t.getSurfaceControl());
t.destroy();
assertNull(t.getSurfaceControl());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index 8cd97cb8a344..428d869fe3cd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -255,6 +255,7 @@ public class WindowFrameTests extends WindowTestsBase {
@Test
public void testLayoutNonfullscreenTask() {
+ removeGlobalMinSizeRestriction();
final DisplayInfo displayInfo = mWm.getDefaultDisplayContentLocked().getDisplayInfo();
final int logicalWidth = displayInfo.logicalWidth;
final int logicalHeight = displayInfo.logicalHeight;
@@ -264,8 +265,8 @@ public class WindowFrameTests extends WindowTestsBase {
WindowState w = createWindow();
final Task task = w.getTask();
// Use split-screen because it is non-fullscreen, but also not floating
- task.mTaskRecord.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
- task.mTaskRecord.setBounds(taskBounds);
+ task.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ task.setBounds(taskBounds);
// The bounds we are requesting might be different from what the system resolved based on
// other factors.
final Rect resolvedTaskBounds = task.getBounds();
@@ -303,8 +304,8 @@ public class WindowFrameTests extends WindowTestsBase {
final int insetTop = logicalHeight / 5;
final int insetRight = insetLeft + (resolvedTaskBounds.right - resolvedTaskBounds.left);
final int insetBottom = insetTop + (resolvedTaskBounds.bottom - resolvedTaskBounds.top);
- task.mTaskRecord.setDisplayedBounds(resolvedTaskBounds);
- task.mTaskRecord.setBounds(insetLeft, insetTop, insetRight, insetBottom);
+ task.setOverrideDisplayedBounds(resolvedTaskBounds);
+ task.setBounds(insetLeft, insetTop, insetRight, insetBottom);
windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
w.computeFrameLw();
assertEquals(resolvedTaskBounds, w.getFrameLw());
@@ -477,7 +478,7 @@ public class WindowFrameTests extends WindowTestsBase {
WindowState w = createWindow();
final Task task = w.getTask();
w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
- task.mTaskRecord.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ task.setWindowingMode(WINDOWING_MODE_FREEFORM);
DisplayContent dc = mTestDisplayContent;
dc.mInputMethodTarget = w;
@@ -499,7 +500,7 @@ public class WindowFrameTests extends WindowTestsBase {
// First check that it only gets moved up enough to show window.
final Rect winRect = new Rect(200, 200, 300, 500);
- task.mTaskRecord.setBounds(winRect);
+ task.setBounds(winRect);
w.getWindowFrames().setFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
w.computeFrameLw();
@@ -511,7 +512,7 @@ public class WindowFrameTests extends WindowTestsBase {
// Now check that it won't get moved beyond the top and then has appropriate insets
winRect.bottom = 600;
- task.mTaskRecord.setBounds(winRect);
+ task.setBounds(winRect);
w.setBounds(winRect);
w.getWindowFrames().setFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
w.computeFrameLw();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index 51daf6567a47..3f32e33a76ec 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -42,7 +42,7 @@ class WindowTestUtils {
.setUserId(userId)
.setStack(stack.mActivityStack)
.build();
- return task.mTask;
+ return task;
}
}
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 780fed9805cb..c3f59eb75460 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -384,7 +384,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
}
/** Sets the default minimum task size to 1 so that tests can use small task sizes */
- public void removeGlobalMinSizeRestriction() {
+ void removeGlobalMinSizeRestriction() {
mWm.mAtmService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp = 1;
}
}
diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp
index c380d291d573..7cc233b2439e 100644
--- a/startop/view_compiler/Android.bp
+++ b/startop/view_compiler/Android.bp
@@ -16,7 +16,6 @@
cc_defaults {
name: "viewcompiler_defaults",
- defaults: ["libdexfile_static_defaults"],
header_libs: [
"libbase_headers",
],
@@ -30,6 +29,7 @@ cc_defaults {
"liblog",
"libutils",
"libziparchive",
+ "libz",
],
cppflags: ["-std=c++17"],
target: {
diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc
index 48b44d0fc99b..50cf5a50d7a8 100644
--- a/startop/view_compiler/dex_builder.cc
+++ b/startop/view_compiler/dex_builder.cc
@@ -16,8 +16,6 @@
#include "dex_builder.h"
-#include "dex/descriptors_names.h"
-
#include <fstream>
#include <memory>
@@ -30,8 +28,6 @@ using std::string;
using ::dex::kAccPublic;
using Op = Instruction::Op;
-using Opcode = ::art::Instruction::Code;
-
const TypeDescriptor TypeDescriptor::Int() { return TypeDescriptor{"I"}; };
const TypeDescriptor TypeDescriptor::Void() { return TypeDescriptor{"V"}; };
@@ -43,20 +39,29 @@ constexpr uint8_t kDexFileMagic[]{0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x38, 0x00
constexpr size_t kMaxEncodedStringLength{5};
// Converts invoke-* to invoke-*/range
-constexpr Opcode InvokeToInvokeRange(Opcode opcode) {
+constexpr ::dex::Opcode InvokeToInvokeRange(::dex::Opcode opcode) {
switch (opcode) {
- case ::art::Instruction::INVOKE_VIRTUAL:
- return ::art::Instruction::INVOKE_VIRTUAL_RANGE;
- case ::art::Instruction::INVOKE_DIRECT:
- return ::art::Instruction::INVOKE_DIRECT_RANGE;
- case ::art::Instruction::INVOKE_STATIC:
- return ::art::Instruction::INVOKE_STATIC_RANGE;
- case ::art::Instruction::INVOKE_INTERFACE:
- return ::art::Instruction::INVOKE_INTERFACE_RANGE;
+ case ::dex::Opcode::OP_INVOKE_VIRTUAL:
+ return ::dex::Opcode::OP_INVOKE_VIRTUAL_RANGE;
+ case ::dex::Opcode::OP_INVOKE_DIRECT:
+ return ::dex::Opcode::OP_INVOKE_DIRECT_RANGE;
+ case ::dex::Opcode::OP_INVOKE_STATIC:
+ return ::dex::Opcode::OP_INVOKE_STATIC_RANGE;
+ case ::dex::Opcode::OP_INVOKE_INTERFACE:
+ return ::dex::Opcode::OP_INVOKE_INTERFACE_RANGE;
default:
LOG(FATAL) << opcode << " is not a recognized invoke opcode.";
- UNREACHABLE();
+ __builtin_unreachable();
+ }
+}
+
+std::string DotToDescriptor(const char* class_name) {
+ std::string descriptor(class_name);
+ std::replace(descriptor.begin(), descriptor.end(), '.', '/');
+ if (descriptor.length() > 0 && descriptor[0] != '[') {
+ descriptor = "L" + descriptor + ";";
}
+ return descriptor;
}
} // namespace
@@ -178,7 +183,7 @@ void WriteTestDexFile(const string& filename) {
}
TypeDescriptor TypeDescriptor::FromClassname(const std::string& name) {
- return TypeDescriptor{art::DotToDescriptor(name.c_str())};
+ return TypeDescriptor{DotToDescriptor(name.c_str())};
}
DexBuilder::DexBuilder() : dex_file_{std::make_shared<ir::DexFile>()} {
@@ -219,11 +224,11 @@ ir::String* DexBuilder::GetOrAddString(const std::string& string) {
ClassBuilder DexBuilder::MakeClass(const std::string& name) {
auto* class_def = Alloc<ir::Class>();
- ir::Type* type_def = GetOrAddType(art::DotToDescriptor(name.c_str()));
+ ir::Type* type_def = GetOrAddType(DotToDescriptor(name.c_str()));
type_def->class_def = class_def;
class_def->type = type_def;
- class_def->super_class = GetOrAddType(art::DotToDescriptor("java.lang.Object"));
+ class_def->super_class = GetOrAddType(DotToDescriptor("java.lang.Object"));
class_def->access_flags = kAccPublic;
return ClassBuilder{this, name, class_def};
}
@@ -378,26 +383,26 @@ void MethodBuilder::EncodeInstructions() {
void MethodBuilder::EncodeInstruction(const Instruction& instruction) {
switch (instruction.opcode()) {
case Instruction::Op::kReturn:
- return EncodeReturn(instruction, ::art::Instruction::RETURN);
+ return EncodeReturn(instruction, ::dex::Opcode::OP_RETURN);
case Instruction::Op::kReturnObject:
- return EncodeReturn(instruction, ::art::Instruction::RETURN_OBJECT);
+ return EncodeReturn(instruction, ::dex::Opcode::OP_RETURN_OBJECT);
case Instruction::Op::kMove:
case Instruction::Op::kMoveObject:
return EncodeMove(instruction);
case Instruction::Op::kInvokeVirtual:
- return EncodeInvoke(instruction, art::Instruction::INVOKE_VIRTUAL);
+ return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_VIRTUAL);
case Instruction::Op::kInvokeDirect:
- return EncodeInvoke(instruction, art::Instruction::INVOKE_DIRECT);
+ return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_DIRECT);
case Instruction::Op::kInvokeStatic:
- return EncodeInvoke(instruction, art::Instruction::INVOKE_STATIC);
+ return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_STATIC);
case Instruction::Op::kInvokeInterface:
- return EncodeInvoke(instruction, art::Instruction::INVOKE_INTERFACE);
+ return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_INTERFACE);
case Instruction::Op::kBindLabel:
return BindLabel(instruction.args()[0]);
case Instruction::Op::kBranchEqz:
- return EncodeBranch(art::Instruction::IF_EQZ, instruction);
+ return EncodeBranch(::dex::Opcode::OP_IF_EQZ, instruction);
case Instruction::Op::kBranchNEqz:
- return EncodeBranch(art::Instruction::IF_NEZ, instruction);
+ return EncodeBranch(::dex::Opcode::OP_IF_NEZ, instruction);
case Instruction::Op::kNew:
return EncodeNew(instruction);
case Instruction::Op::kCheckCast:
@@ -410,10 +415,10 @@ void MethodBuilder::EncodeInstruction(const Instruction& instruction) {
}
}
-void MethodBuilder::EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode) {
+void MethodBuilder::EncodeReturn(const Instruction& instruction, ::dex::Opcode opcode) {
CHECK(!instruction.dest().has_value());
if (instruction.args().size() == 0) {
- Encode10x(art::Instruction::RETURN_VOID);
+ Encode10x(::dex::Opcode::OP_RETURN_VOID);
} else {
CHECK_EQ(1, instruction.args().size());
size_t source = RegisterValue(instruction.args()[0]);
@@ -433,27 +438,27 @@ void MethodBuilder::EncodeMove(const Instruction& instruction) {
if (source.is_immediate()) {
// TODO: support more registers
CHECK_LT(RegisterValue(*instruction.dest()), 16);
- Encode11n(art::Instruction::CONST_4, RegisterValue(*instruction.dest()), source.value());
+ Encode11n(::dex::Opcode::OP_CONST_4, RegisterValue(*instruction.dest()), source.value());
} else if (source.is_string()) {
constexpr size_t kMaxRegisters = 256;
CHECK_LT(RegisterValue(*instruction.dest()), kMaxRegisters);
CHECK_LT(source.value(), 65536); // make sure we don't need a jumbo string
- Encode21c(::art::Instruction::CONST_STRING, RegisterValue(*instruction.dest()), source.value());
+ Encode21c(::dex::Opcode::OP_CONST_STRING, RegisterValue(*instruction.dest()), source.value());
} else if (source.is_variable()) {
// For the moment, we only use this when we need to reshuffle registers for
// an invoke instruction, meaning we are too big for the 4-bit version.
// We'll err on the side of caution and always generate the 16-bit form of
// the instruction.
- Opcode opcode = instruction.opcode() == Instruction::Op::kMove
- ? ::art::Instruction::MOVE_16
- : ::art::Instruction::MOVE_OBJECT_16;
+ auto opcode = instruction.opcode() == Instruction::Op::kMove
+ ? ::dex::Opcode::OP_MOVE_16
+ : ::dex::Opcode::OP_MOVE_OBJECT_16;
Encode32x(opcode, RegisterValue(*instruction.dest()), RegisterValue(source));
} else {
UNIMPLEMENTED(FATAL);
}
}
-void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode) {
+void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::dex::Opcode opcode) {
constexpr size_t kMaxArgs = 5;
// Currently, we only support up to 5 arguments.
@@ -480,8 +485,8 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct
for (size_t i = 0; i < instruction.args().size(); ++i) {
Instruction::Op move_op;
- if (opcode == ::art::Instruction::INVOKE_VIRTUAL ||
- opcode == ::art::Instruction::INVOKE_DIRECT) {
+ if (opcode == ::dex::Opcode::OP_INVOKE_VIRTUAL ||
+ opcode == ::dex::Opcode::OP_INVOKE_DIRECT) {
// In this case, there is an implicit `this` argument, which is always an object.
if (i == 0) {
move_op = Instruction::Op::kMoveObject;
@@ -514,8 +519,8 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct
// If there is a return value, add a move-result instruction
if (instruction.dest().has_value()) {
- Encode11x(instruction.result_is_object() ? art::Instruction::MOVE_RESULT_OBJECT
- : art::Instruction::MOVE_RESULT,
+ Encode11x(instruction.result_is_object() ? ::dex::Opcode::OP_MOVE_RESULT_OBJECT
+ : ::dex::Opcode::OP_MOVE_RESULT,
RegisterValue(*instruction.dest()));
}
@@ -523,7 +528,7 @@ void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruct
}
// Encodes a conditional branch that tests a single argument.
-void MethodBuilder::EncodeBranch(art::Instruction::Code op, const Instruction& instruction) {
+void MethodBuilder::EncodeBranch(::dex::Opcode op, const Instruction& instruction) {
const auto& args = instruction.args();
const auto& test_value = args[0];
const auto& branch_target = args[1];
@@ -546,7 +551,7 @@ void MethodBuilder::EncodeNew(const Instruction& instruction) {
const Value& type = instruction.args()[0];
CHECK_LT(RegisterValue(*instruction.dest()), 256);
CHECK(type.is_type());
- Encode21c(::art::Instruction::NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value());
+ Encode21c(::dex::Opcode::OP_NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value());
}
void MethodBuilder::EncodeCast(const Instruction& instruction) {
@@ -558,7 +563,7 @@ void MethodBuilder::EncodeCast(const Instruction& instruction) {
const Value& type = instruction.args()[0];
CHECK_LT(RegisterValue(*instruction.dest()), 256);
CHECK(type.is_type());
- Encode21c(::art::Instruction::CHECK_CAST, RegisterValue(*instruction.dest()), type.value());
+ Encode21c(::dex::Opcode::OP_CHECK_CAST, RegisterValue(*instruction.dest()), type.value());
}
void MethodBuilder::EncodeFieldOp(const Instruction& instruction) {
@@ -569,7 +574,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) {
CHECK(instruction.dest()->is_variable());
CHECK_EQ(0, instruction.args().size());
- Encode21c(::art::Instruction::SGET,
+ Encode21c(::dex::Opcode::OP_SGET,
RegisterValue(*instruction.dest()),
instruction.index_argument());
break;
@@ -579,7 +584,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) {
CHECK_EQ(1, args.size());
CHECK(args[0].is_variable());
- Encode21c(::art::Instruction::SPUT, RegisterValue(args[0]), instruction.index_argument());
+ Encode21c(::dex::Opcode::OP_SPUT, RegisterValue(args[0]), instruction.index_argument());
break;
}
case Instruction::Op::kGetInstanceField: {
@@ -587,7 +592,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) {
CHECK(instruction.dest()->is_variable());
CHECK_EQ(1, instruction.args().size());
- Encode22c(::art::Instruction::IGET,
+ Encode22c(::dex::Opcode::OP_IGET,
RegisterValue(*instruction.dest()),
RegisterValue(args[0]),
instruction.index_argument());
@@ -599,7 +604,7 @@ void MethodBuilder::EncodeFieldOp(const Instruction& instruction) {
CHECK(args[0].is_variable());
CHECK(args[1].is_variable());
- Encode22c(::art::Instruction::IPUT,
+ Encode22c(::dex::Opcode::OP_IPUT,
RegisterValue(args[1]),
RegisterValue(args[0]),
instruction.index_argument());
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h
index 3924e77fab59..eb2dc88835d4 100644
--- a/startop/view_compiler/dex_builder.h
+++ b/startop/view_compiler/dex_builder.h
@@ -24,7 +24,9 @@
#include <unordered_map>
#include <vector>
-#include "dex/dex_instruction.h"
+#include "android-base/logging.h"
+
+#include "slicer/dex_bytecode.h"
#include "slicer/dex_ir.h"
#include "slicer/writer.h"
@@ -364,11 +366,11 @@ class MethodBuilder {
// Encodes a return instruction. For instructions with no return value, the opcode field is
// ignored. Otherwise, this specifies which return instruction will be used (return,
// return-object, etc.)
- void EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode);
+ void EncodeReturn(const Instruction& instruction, ::dex::Opcode opcode);
void EncodeMove(const Instruction& instruction);
- void EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode);
- void EncodeBranch(art::Instruction::Code op, const Instruction& instruction);
+ void EncodeInvoke(const Instruction& instruction, ::dex::Opcode opcode);
+ void EncodeBranch(::dex::Opcode op, const Instruction& instruction);
void EncodeNew(const Instruction& instruction);
void EncodeCast(const Instruction& instruction);
void EncodeFieldOp(const Instruction& instruction);
@@ -377,17 +379,23 @@ class MethodBuilder {
// https://source.android.com/devices/tech/dalvik/instruction-formats for documentation of
// formats.
- inline void Encode10x(art::Instruction::Code opcode) {
+ inline uint8_t ToBits(::dex::Opcode opcode) {
+ static_assert(sizeof(uint8_t) == sizeof(::dex::Opcode));
+ return static_cast<uint8_t>(opcode);
+ }
+
+ inline void Encode10x(::dex::Opcode opcode) {
// 00|op
- buffer_.push_back(opcode);
+ static_assert(sizeof(uint8_t) == sizeof(::dex::Opcode));
+ buffer_.push_back(ToBits(opcode));
}
- inline void Encode11x(art::Instruction::Code opcode, uint8_t a) {
+ inline void Encode11x(::dex::Opcode opcode, uint8_t a) {
// aa|op
- buffer_.push_back((a << 8) | opcode);
+ buffer_.push_back((a << 8) | ToBits(opcode));
}
- inline void Encode11n(art::Instruction::Code opcode, uint8_t a, int8_t b) {
+ inline void Encode11n(::dex::Opcode opcode, uint8_t a, int8_t b) {
// b|a|op
// Make sure the fields are in bounds (4 bits for a, 4 bits for b).
@@ -395,30 +403,30 @@ class MethodBuilder {
CHECK_LE(-8, b);
CHECK_LT(b, 8);
- buffer_.push_back(((b & 0xf) << 12) | (a << 8) | opcode);
+ buffer_.push_back(((b & 0xf) << 12) | (a << 8) | ToBits(opcode));
}
- inline void Encode21c(art::Instruction::Code opcode, uint8_t a, uint16_t b) {
+ inline void Encode21c(::dex::Opcode opcode, uint8_t a, uint16_t b) {
// aa|op|bbbb
- buffer_.push_back((a << 8) | opcode);
+ buffer_.push_back((a << 8) | ToBits(opcode));
buffer_.push_back(b);
}
- inline void Encode22c(art::Instruction::Code opcode, uint8_t a, uint8_t b, uint16_t c) {
+ inline void Encode22c(::dex::Opcode opcode, uint8_t a, uint8_t b, uint16_t c) {
// b|a|op|bbbb
CHECK(IsShortRegister(a));
CHECK(IsShortRegister(b));
- buffer_.push_back((b << 12) | (a << 8) | opcode);
+ buffer_.push_back((b << 12) | (a << 8) | ToBits(opcode));
buffer_.push_back(c);
}
- inline void Encode32x(art::Instruction::Code opcode, uint16_t a, uint16_t b) {
- buffer_.push_back(opcode);
+ inline void Encode32x(::dex::Opcode opcode, uint16_t a, uint16_t b) {
+ buffer_.push_back(ToBits(opcode));
buffer_.push_back(a);
buffer_.push_back(b);
}
- inline void Encode35c(art::Instruction::Code opcode, size_t a, uint16_t b, uint8_t c, uint8_t d,
+ inline void Encode35c(::dex::Opcode opcode, size_t a, uint16_t b, uint8_t c, uint8_t d,
uint8_t e, uint8_t f, uint8_t g) {
// a|g|op|bbbb|f|e|d|c
@@ -428,14 +436,14 @@ class MethodBuilder {
CHECK(IsShortRegister(e));
CHECK(IsShortRegister(f));
CHECK(IsShortRegister(g));
- buffer_.push_back((a << 12) | (g << 8) | opcode);
+ buffer_.push_back((a << 12) | (g << 8) | ToBits(opcode));
buffer_.push_back(b);
buffer_.push_back((f << 12) | (e << 8) | (d << 4) | c);
}
- inline void Encode3rc(art::Instruction::Code opcode, size_t a, uint16_t b, uint16_t c) {
+ inline void Encode3rc(::dex::Opcode opcode, size_t a, uint16_t b, uint16_t c) {
CHECK_LE(a, 255);
- buffer_.push_back((a << 8) | opcode);
+ buffer_.push_back((a << 8) | ToBits(opcode));
buffer_.push_back(b);
buffer_.push_back(c);
}
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index afa35b4d4de3..a0aa60b74ba0 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -45,6 +45,7 @@ public final class AccessNetworkConstants {
* @hide
*/
@SystemApi
+ @TestApi
public static final int TRANSPORT_TYPE_INVALID = -1;
/**
diff --git a/telephony/java/android/telephony/CallQuality.java b/telephony/java/android/telephony/CallQuality.java
index 028280c332e2..e01deb2802ff 100644
--- a/telephony/java/android/telephony/CallQuality.java
+++ b/telephony/java/android/telephony/CallQuality.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -40,6 +41,7 @@ import java.util.Objects;
* @hide
*/
@SystemApi
+@TestApi
public final class CallQuality implements Parcelable {
// Constants representing the call quality level (see #CallQuality);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index dbada25f50a8..1e245584b1a3 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2840,6 +2840,27 @@ public class CarrierConfigManager {
*/
public static final String KEY_5G_WATCHDOG_TIME_MS_LONG =
"5g_watchdog_time_long";
+ /**
+ * Controls whether to switch data to primary from opportunistic subscription
+ * if primary is out of service. This control only affects system or 1st party app
+ * initiated data switch, but will not override data switch initiated by privileged carrier apps
+ * This carrier config is used to disable this feature.
+ * @hide
+ */
+ public static final String KEY_SWITCH_DATA_TO_PRIMARY_IF_PRIMARY_IS_OOS_BOOL =
+ "switch_data_to_primary_if_primary_is_oos_bool";
+
+ /**
+ * Controls back off time in milli seconds for switching back to
+ * opportunistic subscription. This time will be added to
+ * {@link CarrierConfigManager#KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG} to
+ * determine hysteresis time if there is frequent switching
+ * (determined by system app or 1st party app) between primary and opportunistic
+ * subscription.
+ * @hide
+ */
+ public static final String KEY_OPPORTUNISTIC_NETWORK_BACKOFF_TIME_LONG =
+ "opportunistic_network_backoff_time_long";
/**
* Indicates zero or more emergency number prefix(es), because some carrier requires
@@ -3648,6 +3669,9 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_PING_TEST_BEFORE_DATA_SWITCH_BOOL, true);
/* Default value is 1 hour. */
sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000);
+ sDefaults.putBoolean(KEY_SWITCH_DATA_TO_PRIMARY_IF_PRIMARY_IS_OOS_BOOL, true);
+ /* Default value is 10 seconds. */
+ sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_BACKOFF_TIME_LONG, 10000);
sDefaults.putAll(Gps.getDefaults());
sDefaults.putAll(Wifi.getDefaults());
sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY,
diff --git a/telephony/java/com/android/internal/telephony/CbGeoUtils.java b/telephony/java/android/telephony/CbGeoUtils.java
index 0b73252a1e1b..f4ce6e75769c 100644
--- a/telephony/java/com/android/internal/telephony/CbGeoUtils.java
+++ b/telephony/java/android/telephony/CbGeoUtils.java
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package com.android.internal.telephony;
+package android.telephony;
import android.annotation.NonNull;
-import android.telephony.Rlog;
+import android.annotation.SystemApi;
import android.text.TextUtils;
import java.util.ArrayList;
@@ -30,8 +30,17 @@ import java.util.stream.Collectors;
* The coordinates used by this utils class are latitude and longitude, but some algorithms in this
* class only use them as coordinates on plane, so the calculation will be inaccurate. So don't use
* this class for anything other then geo-targeting of cellbroadcast messages.
+ * @hide
*/
+@SystemApi
public class CbGeoUtils {
+
+ /**
+ * This class is never instantiated
+ * @hide
+ */
+ private CbGeoUtils() {}
+
/** Geometric interface. */
public interface Geometry {
/**
@@ -39,27 +48,36 @@ public class CbGeoUtils {
* @param p point in latitude, longitude format.
* @return {@code True} if the given point is inside the geometry.
*/
- boolean contains(LatLng p);
+ boolean contains(@NonNull LatLng p);
}
/**
* Tolerance for determining if the value is 0. If the absolute value of a value is less than
* this tolerance, it will be treated as 0.
+ * @hide
*/
public static final double EPS = 1e-7;
- /** The radius of earth. */
+ /**
+ * The radius of earth.
+ * @hide
+ */
public static final int EARTH_RADIUS_METER = 6371 * 1000;
private static final String TAG = "CbGeoUtils";
- /** The TLV tags of WAC, defined in ATIS-0700041 5.2.3 WAC tag coding. */
+ // The TLV tags of WAC, defined in ATIS-0700041 5.2.3 WAC tag coding.
+ /** @hide */
public static final int GEO_FENCING_MAXIMUM_WAIT_TIME = 0x01;
+ /** @hide */
public static final int GEOMETRY_TYPE_POLYGON = 0x02;
+ /** @hide */
public static final int GEOMETRY_TYPE_CIRCLE = 0x03;
- /** The identifier of geometry in the encoded string. */
+ // The identifier of geometry in the encoded string.
+ /** @hide */
private static final String CIRCLE_SYMBOL = "circle";
+ /** @hide */
private static final String POLYGON_SYMBOL = "polygon";
/** Point represent by (latitude, longitude). */
@@ -81,7 +99,8 @@ public class CbGeoUtils {
* @param p the point use to calculate the subtraction result.
* @return the result of this point subtract the given point {@code p}.
*/
- public LatLng subtract(LatLng p) {
+ @NonNull
+ public LatLng subtract(@NonNull LatLng p) {
return new LatLng(lat - p.lat, lng - p.lng);
}
@@ -90,7 +109,7 @@ public class CbGeoUtils {
* @param p the point use to calculate the distance.
* @return the distance in meter.
*/
- public double distance(LatLng p) {
+ public double distance(@NonNull LatLng p) {
double dlat = Math.sin(0.5 * Math.toRadians(lat - p.lat));
double dlng = Math.sin(0.5 * Math.toRadians(lng - p.lng));
double x = dlat * dlat
@@ -106,6 +125,7 @@ public class CbGeoUtils {
/**
* The class represents a simple polygon with at least 3 points.
+ * @hide
*/
public static class Polygon implements Geometry {
/**
@@ -239,7 +259,10 @@ public class CbGeoUtils {
}
}
- /** The class represents a circle. */
+ /**
+ * The class represents a circle.
+ * @hide
+ */
public static class Circle implements Geometry {
private final LatLng mCenter;
private final double mRadiusMeter;
@@ -266,6 +289,7 @@ public class CbGeoUtils {
/**
* Parse the geometries from the encoded string {@code str}. The string must follow the
* geometry encoding specified by {@link android.provider.Telephony.CellBroadcasts#GEOMETRIES}.
+ * @hide
*/
@NonNull
public static List<Geometry> parseGeometriesFromString(@NonNull String str) {
@@ -297,6 +321,7 @@ public class CbGeoUtils {
*
* @param geometries the list of geometry objects need to be encoded.
* @return the encoded string.
+ * @hide
*/
@NonNull
public static String encodeGeometriesToString(List<Geometry> geometries) {
@@ -313,6 +338,7 @@ public class CbGeoUtils {
* {@link android.provider.Telephony.CellBroadcasts#GEOMETRIES}.
* @param geometry the geometry object need to be encoded.
* @return the encoded string.
+ * @hide
*/
@NonNull
private static String encodeGeometryToString(@NonNull Geometry geometry) {
@@ -351,6 +377,7 @@ public class CbGeoUtils {
*
* @param str encoded lat/lng string.
* @Return {@link LatLng} object.
+ * @hide
*/
@NonNull
public static LatLng parseLatLngFromString(@NonNull String str) {
@@ -361,6 +388,7 @@ public class CbGeoUtils {
/**
* @Return the sign of the given value {@code value} with the specified tolerance. Return 1
* means the sign is positive, -1 means negative, 0 means the value will be treated as 0.
+ * @hide
*/
public static int sign(double value) {
if (value > EPS) return 1;
diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java
new file mode 100644
index 000000000000..02d8be3ccfd5
--- /dev/null
+++ b/telephony/java/android/telephony/ImsManager.java
@@ -0,0 +1,66 @@
+/*
+ * 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.telephony.ims;
+
+import android.annotation.SystemService;
+import android.content.Context;
+import android.telephony.SubscriptionManager;
+
+/**
+ * Provides access to information about Telephony IMS services on the device.
+ *
+ * @hide
+ */
+@SystemService(Context.TELEPHONY_IMS_SERVICE)
+public class ImsManager {
+
+ private Context mContext;
+
+ public ImsManager(Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Create an instance of ImsRcsManager for the subscription id specified.
+ *
+ * @param subscriptionId The ID of the subscription that this ImsRcsManager will use.
+ * @throws IllegalArgumentException if the subscription is invalid.
+ * @return a ImsRcsManager instance with the specific subscription ID.
+ */
+ public ImsRcsManager getImsRcsManager(int subscriptionId) {
+ if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) {
+ throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
+ }
+
+ return new ImsRcsManager(mContext, subscriptionId);
+ }
+
+ /**
+ * Create an instance of ImsMmTelManager for the subscription id specified.
+ *
+ * @param subscriptionId The ID of the subscription that this ImsMmTelManager will use.
+ * @throws IllegalArgumentException if the subscription is invalid.
+ * @return a ImsMmTelManager instance with the specific subscription ID.
+ */
+ public ImsMmTelManager getImsMmTelManager(int subscriptionId) {
+ if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) {
+ throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
+ }
+
+ return new ImsMmTelManager(subscriptionId);
+ }
+}
diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java
index dc991b9a3ea7..3e044e52d28b 100644
--- a/telephony/java/android/telephony/SmsCbMessage.java
+++ b/telephony/java/android/telephony/SmsCbMessage.java
@@ -25,9 +25,7 @@ import android.database.Cursor;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.Telephony.CellBroadcasts;
-
-import com.android.internal.telephony.CbGeoUtils;
-import com.android.internal.telephony.CbGeoUtils.Geometry;
+import android.telephony.CbGeoUtils.Geometry;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -414,9 +412,8 @@ public final class SmsCbMessage implements Parcelable {
/**
* Get the Geo-Fencing Maximum Wait Time.
* @return the time in second.
- * @hide
*/
- public int getMaximumWaitingTime() {
+ public int getMaximumWaitingDuration() {
return mMaximumWaitTimeSec;
}
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 2c16110ceb4c..0bf2aa7d0e96 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -78,11 +78,6 @@ public final class SmsManager {
SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
private static final Object sLockObject = new Object();
- /** @hide */
- public static final int CELL_BROADCAST_RAN_TYPE_GSM = 0;
- /** @hide */
- public static final int CELL_BROADCAST_RAN_TYPE_CDMA = 1;
-
/** SMS record length from TS 51.011 10.5.3
* @hide
*/
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index b5e91d0bad85..352d5071df56 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -31,6 +31,7 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SuppressAutoDoc;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.app.BroadcastOptions;
import android.app.PendingIntent;
@@ -155,6 +156,7 @@ public class SubscriptionManager {
*/
@NonNull
@SystemApi
+ @TestApi
public static final Uri WFC_ENABLED_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc");
/**
@@ -174,6 +176,7 @@ public class SubscriptionManager {
*/
@NonNull
@SystemApi
+ @TestApi
public static final Uri ADVANCED_CALLING_ENABLED_CONTENT_URI = Uri.withAppendedPath(
CONTENT_URI, "advanced_calling");
@@ -192,6 +195,7 @@ public class SubscriptionManager {
*/
@NonNull
@SystemApi
+ @TestApi
public static final Uri WFC_MODE_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc_mode");
/**
@@ -209,6 +213,7 @@ public class SubscriptionManager {
*/
@NonNull
@SystemApi
+ @TestApi
public static final Uri WFC_ROAMING_MODE_CONTENT_URI = Uri.withAppendedPath(
CONTENT_URI, "wfc_roaming_mode");
@@ -228,6 +233,7 @@ public class SubscriptionManager {
*/
@NonNull
@SystemApi
+ @TestApi
public static final Uri VT_ENABLED_CONTENT_URI = Uri.withAppendedPath(
CONTENT_URI, "vt_enabled");
@@ -246,6 +252,7 @@ public class SubscriptionManager {
*/
@NonNull
@SystemApi
+ @TestApi
public static final Uri WFC_ROAMING_ENABLED_CONTENT_URI = Uri.withAppendedPath(
CONTENT_URI, "wfc_roaming_enabled");
@@ -2371,12 +2378,10 @@ public class SubscriptionManager {
* @param plans the list of plans. The first plan is always the primary and
* most important plan. Any additional plans are secondary and
* may not be displayed or used by decision making logic.
- * The list of all plans must meet the requirements defined in
- * {@link SubscriptionPlan.Builder#setNetworkTypes(int[])}.
* @throws SecurityException if the caller doesn't meet the requirements
* outlined above.
* @throws IllegalArgumentException if plans don't meet the requirements
- * mentioned above.
+ * defined in {@link SubscriptionPlan}.
*/
public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) {
try {
diff --git a/telephony/java/android/telephony/SubscriptionPlan.java b/telephony/java/android/telephony/SubscriptionPlan.java
index e24eb2696c6c..28a5c2086ede 100644
--- a/telephony/java/android/telephony/SubscriptionPlan.java
+++ b/telephony/java/android/telephony/SubscriptionPlan.java
@@ -44,6 +44,14 @@ import java.util.Objects;
* as explaining how much mobile data they have remaining, and what will happen
* when they run out.
*
+ * If specifying network types, the developer must supply at least one plan
+ * that applies to all network types (default), and all additional plans
+ * may not include a particular network type more than once.
+ * This is enforced by {@link SubscriptionManager} when setting the plans.
+ *
+ * Plan selection will prefer plans that have specific network types defined
+ * over plans that apply to all network types.
+ *
* @see SubscriptionManager#setSubscriptionPlans(int, java.util.List)
* @see SubscriptionManager#getSubscriptionPlans(int)
*/
@@ -213,7 +221,7 @@ public final class SubscriptionPlan implements Parcelable {
/**
* Return an array containing all {@link NetworkType}s this SubscriptionPlan applies to.
- * A null array means this SubscriptionPlan applies to all network types.
+ * A null value means this SubscriptionPlan applies to all network types.
*/
public @Nullable @NetworkType int[] getNetworkTypes() {
return networkTypes;
@@ -372,20 +380,13 @@ public final class SubscriptionPlan implements Parcelable {
/**
* Set the network types this SubscriptionPlan applies to.
- * The developer must supply at least one plan that applies to all network types (default),
- * and all additional plans may not include a particular network type more than once.
- * Plan selection will prefer plans that have specific network types defined
- * over plans that apply to all network types.
*
* @param networkTypes a set of all {@link NetworkType}s that apply to this plan.
- * A null value or empty array means the plan applies to all network types.
+ * A null value means the plan applies to all network types,
+ * and an empty array means the plan applies to no network types.
*/
public @NonNull Builder setNetworkTypes(@Nullable @NetworkType int[] networkTypes) {
- if (networkTypes == null || networkTypes.length == 0) {
- plan.networkTypes = null;
- } else {
- plan.networkTypes = networkTypes;
- }
+ plan.networkTypes = networkTypes;
return this;
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 0c663f85b99c..5a63eb08860b 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -8029,6 +8029,7 @@ public class TelephonyManager {
/** @hide */
@SystemApi
+ @TestApi
public List<String> getCarrierPackageNamesForIntent(Intent intent) {
return getCarrierPackageNamesForIntentAndPhone(intent, getPhoneId());
}
@@ -9567,18 +9568,37 @@ public class TelephonyManager {
}
/**
- * Resets Telephony and IMS settings back to factory defaults.
+ * Resets telephony manager settings back to factory defaults.
*
* @hide
*/
- @SystemApi
- @RequiresPermission(Manifest.permission.CONNECTIVITY_INTERNAL)
public void factoryReset(int subId) {
try {
Log.d(TAG, "factoryReset: subId=" + subId);
ITelephony telephony = getITelephony();
- if (telephony != null)
+ if (telephony != null) {
telephony.factoryReset(subId);
+ }
+ } catch (RemoteException e) {
+ }
+ }
+
+
+ /**
+ * Resets Telephony and IMS settings back to factory defaults only for the subscription
+ * associated with this instance.
+ * @see #createForSubscriptionId(int)
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.CONNECTIVITY_INTERNAL)
+ public void resetSettings() {
+ try {
+ Log.d(TAG, "resetSettings: subId=" + getSubId());
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ telephony.factoryReset(getSubId());
+ }
} catch (RemoteException e) {
}
}
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index a5d62669de05..60774e7f1e7f 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1944,8 +1944,9 @@ public class ApnSetting implements Parcelable {
* {@link ApnSetting} built from this builder otherwise.
*/
public ApnSetting build() {
- if ((mApnTypeBitmask & TYPE_ALL) == 0 || TextUtils.isEmpty(mApnName)
- || TextUtils.isEmpty(mEntryName)) {
+ if ((mApnTypeBitmask & (TYPE_DEFAULT | TYPE_MMS | TYPE_SUPL | TYPE_DUN | TYPE_HIPRI |
+ TYPE_FOTA | TYPE_IMS | TYPE_CBS | TYPE_IA | TYPE_EMERGENCY | TYPE_MCX)) == 0
+ || TextUtils.isEmpty(mApnName) || TextUtils.isEmpty(mEntryName)) {
return null;
}
return new ApnSetting(this);
diff --git a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
index 79cdfef96300..9f09d7a93a82 100644
--- a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
+++ b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
@@ -19,6 +19,7 @@ package android.telephony.ims;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,6 +33,7 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
+@TestApi
public final class ImsCallForwardInfo implements Parcelable {
/**
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 4ddeb908a200..b0ff5dc351e2 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -19,6 +19,7 @@ package android.telephony.ims;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.Parcel;
@@ -45,6 +46,7 @@ import java.util.List;
* @hide
*/
@SystemApi
+@TestApi
public final class ImsCallProfile implements Parcelable {
private static final String TAG = "ImsCallProfile";
diff --git a/telephony/java/android/telephony/ims/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
index a09844d6c0e2..e11886f2bea5 100644
--- a/telephony/java/android/telephony/ims/ImsCallSessionListener.java
+++ b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
@@ -18,6 +18,7 @@ package android.telephony.ims;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.RemoteException;
import android.telephony.CallQuality;
import android.telephony.ims.aidl.IImsCallSessionListener;
@@ -36,6 +37,7 @@ import com.android.ims.internal.IImsCallSession;
// TODO: APIs in here do not conform to API guidelines yet. This can be changed if
// ImsCallSessionListenerConverter is also changed.
@SystemApi
+@TestApi
public class ImsCallSessionListener {
private final IImsCallSessionListener mListener;
diff --git a/telephony/java/android/telephony/ims/ImsConferenceState.java b/telephony/java/android/telephony/ims/ImsConferenceState.java
index 6f062f4185f2..eb6c12cb73e2 100644
--- a/telephony/java/android/telephony/ims/ImsConferenceState.java
+++ b/telephony/java/android/telephony/ims/ImsConferenceState.java
@@ -18,6 +18,7 @@ package android.telephony.ims;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -36,6 +37,7 @@ import java.util.Set;
* @hide
*/
@SystemApi
+@TestApi
public final class ImsConferenceState implements Parcelable {
/**
* conference-info : user
diff --git a/telephony/java/android/telephony/ims/ImsException.java b/telephony/java/android/telephony/ims/ImsException.java
index 6187e67a6acb..39af2e770882 100644
--- a/telephony/java/android/telephony/ims/ImsException.java
+++ b/telephony/java/android/telephony/ims/ImsException.java
@@ -19,6 +19,7 @@ package android.telephony.ims;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.content.pm.PackageManager;
import android.telephony.SubscriptionManager;
import android.text.TextUtils;
@@ -32,6 +33,7 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
+@TestApi
public final class ImsException extends Exception {
/**
diff --git a/telephony/java/android/telephony/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java
index eb2ebcad2c1d..177d9b3343f0 100644
--- a/telephony/java/android/telephony/ims/ImsExternalCallState.java
+++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -34,6 +35,7 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
+@TestApi
public final class ImsExternalCallState implements Parcelable {
private static final String TAG = "ImsExternalCallState";
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 7cafa1ea068c..eb0e2f7b8786 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -24,6 +24,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.content.Context;
import android.os.Binder;
import android.os.RemoteException;
@@ -58,6 +59,7 @@ import java.util.function.Consumer;
* @hide
*/
@SystemApi
+@TestApi
public class ImsMmTelManager implements RegistrationManager {
/**
@@ -254,8 +256,8 @@ public class ImsMmTelManager implements RegistrationManager {
* the {@link ImsService} associated with the subscription is not available. This can happen if
* the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
* reason.
- * @deprecated Use {@link #registerImsRegistrationCallback(
- * RegistrationManager.RegistrationCallback, Executor)} instead.
+ * @deprecated Use {@link RegistrationManager#registerImsRegistrationCallback(Executor,
+ * RegistrationManager.RegistrationCallback)} instead.
*/
@Deprecated
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@@ -285,9 +287,8 @@ public class ImsMmTelManager implements RegistrationManager {
/**{@inheritDoc}*/
@Override
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void registerImsRegistrationCallback(
- @NonNull RegistrationManager.RegistrationCallback c,
- @NonNull @CallbackExecutor Executor executor) throws ImsException {
+ public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull RegistrationManager.RegistrationCallback c) throws ImsException {
if (c == null) {
throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
}
@@ -348,8 +349,8 @@ public class ImsMmTelManager implements RegistrationManager {
/**{@inheritDoc}*/
@Override
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void getRegistrationState(@NonNull @ImsRegistrationState Consumer<Integer> stateCallback,
- @NonNull @CallbackExecutor Executor executor) {
+ public void getRegistrationState(@NonNull @CallbackExecutor Executor executor,
+ @NonNull @ImsRegistrationState Consumer<Integer> stateCallback) {
if (stateCallback == null) {
throw new IllegalArgumentException("Must include a non-null callback.");
}
@@ -371,9 +372,9 @@ public class ImsMmTelManager implements RegistrationManager {
/**{@inheritDoc}*/
@Override
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void getRegistrationTransportType(
- @NonNull @AccessNetworkConstants.TransportType Consumer<Integer> transportTypeCallback,
- @NonNull @CallbackExecutor Executor executor) {
+ public void getRegistrationTransportType(@NonNull @CallbackExecutor Executor executor,
+ @NonNull @AccessNetworkConstants.TransportType
+ Consumer<Integer> transportTypeCallback) {
if (transportTypeCallback == null) {
throw new IllegalArgumentException("Must include a non-null callback.");
}
@@ -607,17 +608,17 @@ public class ImsMmTelManager implements RegistrationManager {
* {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED} broadcast for this subscription.
* @param capability The capability that is being queried for support on the carrier network.
* @param transportType The transport type of the capability to check support for.
+ * @param executor The executor that the callback will be called with.
* @param callback A consumer containing a Boolean result specifying whether or not the
* capability is supported on this carrier network for the transport specified.
- * @param executor The executor that the callback will be called with.
* @throws ImsException if the subscription is no longer valid or the IMS service is not
* available.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void isSupported(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
@AccessNetworkConstants.TransportType int transportType,
- @NonNull Consumer<Boolean> callback,
- @NonNull @CallbackExecutor Executor executor) throws ImsException {
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<Boolean> callback) throws ImsException {
if (callback == null) {
throw new IllegalArgumentException("Must include a non-null Consumer.");
}
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index 25bd1caea431..21707b0d7cfd 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -22,11 +22,15 @@ import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.content.Context;
import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.telephony.AccessNetworkConstants;
-import android.telephony.SubscriptionManager;
import android.telephony.ims.aidl.IImsCapabilityCallback;
+import android.telephony.ims.aidl.IImsRcsController;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.RcsFeature;
+import android.util.Log;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -35,10 +39,11 @@ import java.util.function.Consumer;
* Manager for interfacing with the framework RCS services, including the User Capability Exchange
* (UCE) service, as well as managing user settings.
*
- * Use {@link #createForSubscriptionId(Context, int)} to create an instance of this manager.
+ * Use {@link ImsManager#getImsRcsManager(int)} to create an instance of this manager.
* @hide
*/
public class ImsRcsManager implements RegistrationManager {
+ private static final String TAG = "ImsRcsManager";
/**
* Receives RCS availability status updates from the ImsService.
@@ -112,37 +117,30 @@ public class ImsRcsManager implements RegistrationManager {
private final int mSubId;
private final Context mContext;
-
/**
- * Create an instance of ImsRcsManager for the subscription id specified.
- *
- * @param context The context to create this ImsRcsManager instance within.
- * @param subscriptionId The ID of the subscription that this ImsRcsManager will use.
- * @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
- * @throws IllegalArgumentException if the subscription is invalid.
+ * Use {@link ImsManager#getImsRcsManager(int)} to create an instance of this class.
* @hide
*/
- public static ImsRcsManager createForSubscriptionId(Context context, int subscriptionId) {
- if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) {
- throw new IllegalArgumentException("Invalid subscription ID");
- }
-
- return new ImsRcsManager(context, subscriptionId);
+ public ImsRcsManager(Context context, int subId) {
+ mSubId = subId;
+ mContext = context;
}
/**
- * Use {@link #createForSubscriptionId(Context, int)} to create an instance of this class.
+ * @return A {@link RcsUceAdapter} used for User Capability Exchange (UCE) operations for
+ * this subscription.
+ * @hide
*/
- private ImsRcsManager(Context context, int subId) {
- mContext = context;
- mSubId = subId;
+ @NonNull
+ public RcsUceAdapter getUceAdapter() {
+ return new RcsUceAdapter(mSubId);
}
/**{@inheritDoc}*/
@Override
public void registerImsRegistrationCallback(
- @NonNull RegistrationManager.RegistrationCallback c,
- @NonNull @CallbackExecutor Executor executor)
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull RegistrationCallback c)
throws ImsException {
if (c == null) {
throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
@@ -168,8 +166,8 @@ public class ImsRcsManager implements RegistrationManager {
/**{@inheritDoc}*/
@Override
- public void getRegistrationState(@NonNull @ImsRegistrationState Consumer<Integer> stateCallback,
- @NonNull @CallbackExecutor Executor executor) {
+ public void getRegistrationState(@NonNull @CallbackExecutor Executor executor,
+ @NonNull @ImsRegistrationState Consumer<Integer> stateCallback) {
if (stateCallback == null) {
throw new IllegalArgumentException("Must include a non-null stateCallback.");
}
@@ -182,9 +180,9 @@ public class ImsRcsManager implements RegistrationManager {
/**{@inheritDoc}*/
@Override
- public void getRegistrationTransportType(
- @NonNull @AccessNetworkConstants.TransportType Consumer<Integer> transportTypeCallback,
- @NonNull @CallbackExecutor Executor executor) {
+ public void getRegistrationTransportType(@NonNull @CallbackExecutor Executor executor,
+ @NonNull @AccessNetworkConstants.TransportType
+ Consumer<Integer> transportTypeCallback) {
if (transportTypeCallback == null) {
throw new IllegalArgumentException("Must include a non-null transportTypeCallback.");
}
@@ -225,9 +223,22 @@ public class ImsRcsManager implements RegistrationManager {
if (executor == null) {
throw new IllegalArgumentException("Must include a non-null Executor.");
}
+
+ IImsRcsController imsRcsController = getIImsRcsController();
+ if (imsRcsController == null) {
+ Log.e(TAG, "Register availability callback: IImsRcsController is null");
+ throw new ImsException("Can not find remote IMS service",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+
c.setExecutor(executor);
- throw new UnsupportedOperationException("registerRcsAvailabilityCallback is not"
- + "supported.");
+ try {
+ imsRcsController.registerRcsAvailabilityCallback(c.getBinder());
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling IImsRcsController#registerRcsAvailabilityCallback", e);
+ throw new ImsException("Remote IMS Service is not available",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
}
/**
@@ -238,14 +249,31 @@ public class ImsRcsManager implements RegistrationManager {
* inactive subscription, it will result in a no-op.
* @param c The RCS {@link AvailabilityCallback} to be removed.
* @see #registerRcsAvailabilityCallback(Executor, AvailabilityCallback)
+ * @throws ImsException if the IMS service is not available when calling this method
+ * {@link ImsRcsController#unregisterRcsAvailabilityCallback()}.
+ * See {@link ImsException#getCode()} for more information on the error codes.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void unregisterRcsAvailabilityCallback(@NonNull AvailabilityCallback c) {
+ public void unregisterRcsAvailabilityCallback(@NonNull AvailabilityCallback c)
+ throws ImsException {
if (c == null) {
throw new IllegalArgumentException("Must include a non-null AvailabilityCallback.");
}
- throw new UnsupportedOperationException("unregisterRcsAvailabilityCallback is not"
- + "supported.");
+
+ IImsRcsController imsRcsController = getIImsRcsController();
+ if (imsRcsController == null) {
+ Log.e(TAG, "Unregister availability callback: IImsRcsController is null");
+ throw new ImsException("Can not find remote IMS service",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+
+ try {
+ imsRcsController.unregisterRcsAvailabilityCallback(c.getBinder());
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling IImsRcsController#unregisterRcsAvailabilityCallback", e);
+ throw new ImsException("Remote IMS Service is not available",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
}
/**
@@ -260,10 +288,27 @@ public class ImsRcsManager implements RegistrationManager {
* rather the subscription is capable of this service over IMS.
* @see #isAvailable(int)
* @see android.telephony.CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL
+ * @throws ImsException if the IMS service is not available when calling this method
+ * {@link ImsRcsController#isCapable(int, int)}.
+ * See {@link ImsException#getCode()} for more information on the error codes.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public boolean isCapable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
- throw new UnsupportedOperationException("isCapable is not supported.");
+ public boolean isCapable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability)
+ throws ImsException {
+ IImsRcsController imsRcsController = getIImsRcsController();
+ if (imsRcsController == null) {
+ Log.e(TAG, "isCapable: IImsRcsController is null");
+ throw new ImsException("Can not find remote IMS service",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+
+ try {
+ return imsRcsController.isCapable(mSubId, capability);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling IImsRcsController#isCapable", e);
+ throw new ImsException("Remote IMS Service is not available",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
}
/**
@@ -277,18 +322,31 @@ public class ImsRcsManager implements RegistrationManager {
* false otherwise. If the capability is available, IMS is registered and the service is
* currently available over IMS.
* @see #isCapable(int)
+ * @throws ImsException if the IMS service is not available when calling this method
+ * {@link ImsRcsController#isAvailable(int, int)}.
+ * See {@link ImsException#getCode()} for more information on the error codes.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public boolean isAvailable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
- throw new UnsupportedOperationException("isAvailable is not supported.");
+ public boolean isAvailable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability)
+ throws ImsException {
+ IImsRcsController imsRcsController = getIImsRcsController();
+ if (imsRcsController == null) {
+ Log.e(TAG, "isAvailable: IImsRcsController is null");
+ throw new ImsException("Can not find remote IMS service",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+
+ try {
+ return imsRcsController.isAvailable(mSubId, capability);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling IImsRcsController#isAvailable", e);
+ throw new ImsException("Remote IMS Service is not available",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
}
- /**
- * @return A new {@link RcsUceAdapter} used for User Capability Exchange (UCE) operations for
- * this subscription.
- */
- @NonNull
- public RcsUceAdapter getUceAdapter() {
- return new RcsUceAdapter(mSubId);
+ private IImsRcsController getIImsRcsController() {
+ IBinder binder = ServiceManager.getService(Context.TELEPHONY_IMS_SERVICE);
+ return IImsRcsController.Stub.asInterface(binder);
}
}
diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
index 10251d707c22..663b09a3e96e 100644
--- a/telephony/java/android/telephony/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -19,6 +19,7 @@ package android.telephony.ims;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,6 +33,7 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
+@TestApi
public final class ImsReasonInfo implements Parcelable {
/**
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index e6777c17203a..62bc2ae44573 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -17,6 +17,7 @@
package android.telephony.ims;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
@@ -90,6 +91,7 @@ import com.android.internal.annotations.VisibleForTesting;
* @hide
*/
@SystemApi
+@TestApi
public class ImsService extends Service {
private static final String LOG_TAG = "ImsService";
diff --git a/telephony/java/android/telephony/ims/ImsSsData.java b/telephony/java/android/telephony/ims/ImsSsData.java
index ec2ff6c58a40..6b728599c7d3 100644
--- a/telephony/java/android/telephony/ims/ImsSsData.java
+++ b/telephony/java/android/telephony/ims/ImsSsData.java
@@ -19,6 +19,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Rlog;
@@ -35,6 +36,7 @@ import java.util.List;
* {@hide}
*/
@SystemApi
+@TestApi
public final class ImsSsData implements Parcelable {
private static final String TAG = ImsSsData.class.getCanonicalName();
diff --git a/telephony/java/android/telephony/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java
index 0510a0012426..77bd98411037 100644
--- a/telephony/java/android/telephony/ims/ImsSsInfo.java
+++ b/telephony/java/android/telephony/ims/ImsSsInfo.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -37,6 +38,7 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
+@TestApi
public final class ImsSsInfo implements Parcelable {
/**@hide*/
diff --git a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
index c1f059e1cc89..b7ab0a09a1cb 100644
--- a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
+++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
@@ -18,6 +18,7 @@ package android.telephony.ims;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -29,6 +30,7 @@ import android.os.Parcelable;
* @hide
*/
@SystemApi
+@TestApi
public final class ImsStreamMediaProfile implements Parcelable {
private static final String TAG = "ImsStreamMediaProfile";
diff --git a/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
index 16303685d0a3..f67f68e2e425 100644
--- a/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
+++ b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
@@ -19,6 +19,7 @@ package android.telephony.ims;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -31,6 +32,7 @@ import java.util.Arrays;
* @hide
*/
@SystemApi
+@TestApi
public final class ImsSuppServiceNotification implements Parcelable {
private static final String TAG = "ImsSuppServiceNotification";
diff --git a/telephony/java/android/telephony/ims/ImsUtListener.java b/telephony/java/android/telephony/ims/ImsUtListener.java
index 1a21d0aa0c76..bc12404461c7 100644
--- a/telephony/java/android/telephony/ims/ImsUtListener.java
+++ b/telephony/java/android/telephony/ims/ImsUtListener.java
@@ -18,6 +18,7 @@ package android.telephony.ims;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.ims.stub.ImsUtImplBase;
@@ -33,6 +34,7 @@ import com.android.ims.internal.IImsUtListener;
// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
// will break other implementations of ImsUt maintained by other ImsServices.
@SystemApi
+@TestApi
public class ImsUtListener {
/**
diff --git a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
index 17724018ee57..270e693c8825 100644
--- a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
+++ b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
@@ -17,6 +17,7 @@
package android.telephony.ims;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Handler;
@@ -36,6 +37,7 @@ import com.android.internal.os.SomeArgs;
* @hide
*/
@SystemApi
+@TestApi
public abstract class ImsVideoCallProvider {
private static final int MSG_SET_CALLBACK = 1;
private static final int MSG_SET_CAMERA = 2;
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index effdf48067c3..e16085e30465 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -23,6 +23,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.StringDef;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.WorkerThread;
import android.content.Context;
import android.content.pm.IPackageManager;
@@ -59,6 +60,7 @@ import java.util.concurrent.Executor;
* @hide
*/
@SystemApi
+@TestApi
public class ProvisioningManager {
/**@hide*/
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
index a6a7a84c2c65..b47bcb9b119b 100644
--- a/telephony/java/android/telephony/ims/RcsUceAdapter.java
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -23,6 +23,13 @@ import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.content.Context;
import android.net.Uri;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.telephony.ims.aidl.IImsRcsController;
+import android.telephony.ims.aidl.IRcsUceControllerCallback;
+import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -36,6 +43,7 @@ import java.util.concurrent.Executor;
* @hide
*/
public class RcsUceAdapter {
+ private static final String TAG = "RcsUceAdapter";
/**
* An unknown error has caused the request to fail.
@@ -188,7 +196,6 @@ public class RcsUceAdapter {
/**
* Not to be instantiated directly, use
- * {@link ImsRcsManager#createForSubscriptionId(Context, int)} and
* {@link ImsRcsManager#getUceAdapter()} to instantiate this manager class.
*/
RcsUceAdapter(int subId) {
@@ -218,7 +225,45 @@ public class RcsUceAdapter {
public void requestCapabilities(@CallbackExecutor Executor executor,
@NonNull List<Uri> contactNumbers,
@NonNull CapabilitiesCallback c) throws ImsException {
- throw new UnsupportedOperationException("isUceSettingEnabled is not supported.");
+ if (c == null) {
+ throw new IllegalArgumentException("Must include a non-null AvailabilityCallback.");
+ }
+ if (executor == null) {
+ throw new IllegalArgumentException("Must include a non-null Executor.");
+ }
+ if (contactNumbers == null) {
+ throw new IllegalArgumentException("Must include non-null contact number list.");
+ }
+
+ IImsRcsController imsRcsController = getIImsRcsController();
+ if (imsRcsController == null) {
+ Log.e(TAG, "requestCapabilities: IImsRcsController is null");
+ throw new ImsException("Can not find remote IMS service",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+
+ IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() {
+ @Override
+ public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) {
+ Binder.withCleanCallingIdentity(() ->
+ executor.execute(() ->
+ c.onCapabilitiesReceived(contactCapabilities)));
+ }
+ @Override
+ public void onError(int errorCode) {
+ Binder.withCleanCallingIdentity(() ->
+ executor.execute(() ->
+ c.onError(errorCode)));
+ }
+ };
+
+ try {
+ imsRcsController.requestCapabilities(mSubId, contactNumbers, internalCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling IImsRcsController#requestCapabilities", e);
+ throw new ImsException("Remote IMS Service is not available",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
}
/**
@@ -233,7 +278,20 @@ public class RcsUceAdapter {
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @PublishState int getUcePublishState() throws ImsException {
- throw new UnsupportedOperationException("getPublishState is not supported.");
+ IImsRcsController imsRcsController = getIImsRcsController();
+ if (imsRcsController == null) {
+ Log.e(TAG, "getUcePublishState: IImsRcsController is null");
+ throw new ImsException("Can not find remote IMS service",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+
+ try {
+ return imsRcsController.getUcePublishState(mSubId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling IImsRcsController#getUcePublishState", e);
+ throw new ImsException("Remote IMS Service is not available",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
}
/**
@@ -252,9 +310,22 @@ public class RcsUceAdapter {
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isUceSettingEnabled() throws ImsException {
- // TODO: add SubscriptionController column for this property.
- throw new UnsupportedOperationException("isUceSettingEnabled is not supported.");
+ IImsRcsController imsRcsController = getIImsRcsController();
+ if (imsRcsController == null) {
+ Log.e(TAG, "isUceSettingEnabled: IImsRcsController is null");
+ throw new ImsException("Can not find remote IMS service",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+
+ try {
+ return imsRcsController.isUceSettingEnabled(mSubId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling IImsRcsController#isUceSettingEnabled", e);
+ throw new ImsException("Remote IMS Service is not available",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
}
+
/**
* Change the user’s setting for whether or not UCE is enabled for the associated subscription.
* @param isEnabled the user's setting for whether or not they wish for Presence and User
@@ -270,7 +341,24 @@ public class RcsUceAdapter {
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setUceSettingEnabled(boolean isEnabled) throws ImsException {
- // TODO: add SubscriptionController column for this property.
- throw new UnsupportedOperationException("setUceSettingEnabled is not supported.");
+ IImsRcsController imsRcsController = getIImsRcsController();
+ if (imsRcsController == null) {
+ Log.e(TAG, "setUceSettingEnabled: IImsRcsController is null");
+ throw new ImsException("Can not find remote IMS service",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+
+ try {
+ imsRcsController.setUceSettingEnabled(mSubId, isEnabled);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling IImsRcsController#setUceSettingEnabled", e);
+ throw new ImsException("Remote IMS Service is not available",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+ }
+
+ private IImsRcsController getIImsRcsController() {
+ IBinder binder = ServiceManager.getService(Context.TELEPHONY_IMS_SERVICE);
+ return IImsRcsController.Stub.asInterface(binder);
}
}
diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java
index b4c11e3c32a1..99bb259602e5 100644
--- a/telephony/java/android/telephony/ims/RegistrationManager.java
+++ b/telephony/java/android/telephony/ims/RegistrationManager.java
@@ -23,6 +23,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.net.Uri;
import android.os.Binder;
import android.telephony.AccessNetworkConstants;
@@ -43,6 +44,7 @@ import java.util.function.Consumer;
* @hide
*/
@SystemApi
+@TestApi
public interface RegistrationManager {
/**
@@ -90,7 +92,7 @@ public interface RegistrationManager {
/**
* Callback class for receiving IMS network Registration callback events.
- * @see #registerImsRegistrationCallback(RegistrationCallback, Executor)
+ * @see #registerImsRegistrationCallback(Executor, RegistrationCallback)
* @see #unregisterImsRegistrationCallback(RegistrationCallback)
*/
class RegistrationCallback {
@@ -229,8 +231,8 @@ public interface RegistrationManager {
* When the callback is registered, it will initiate the callback c to be called with the
* current registration state.
*
- * @param c The {@link RegistrationCallback} to be added.
* @param executor The executor the callback events should be run on.
+ * @param c The {@link RegistrationCallback} to be added.
* @see #unregisterImsRegistrationCallback(RegistrationCallback)
* @throws ImsException if the subscription associated with this callback is valid, but
* the {@link ImsService} associated with the subscription is not available. This can happen if
@@ -238,8 +240,8 @@ public interface RegistrationManager {
* reason.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- void registerImsRegistrationCallback(@NonNull RegistrationCallback c,
- @NonNull @CallbackExecutor Executor executor) throws ImsException;
+ void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull RegistrationCallback c) throws ImsException;
/**
* Removes an existing {@link RegistrationCallback}.
@@ -250,36 +252,36 @@ public interface RegistrationManager {
*
* @param c The {@link RegistrationCallback} to be removed.
* @see SubscriptionManager.OnSubscriptionsChangedListener
- * @see #registerImsRegistrationCallback(RegistrationCallback, Executor)
+ * @see #registerImsRegistrationCallback(Executor, RegistrationCallback)
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c);
/**
* Gets the registration state of the IMS service.
- * @param stateCallback A callback called on the supplied {@link Executor} that will contain the
- * registration state of the IMS service, which will be one of the
- * following: {@link #REGISTRATION_STATE_NOT_REGISTERED},
- * {@link #REGISTRATION_STATE_REGISTERING}, or
- * {@link #REGISTRATION_STATE_REGISTERED}.
* @param executor The {@link Executor} that will be used to call the IMS registration state
* callback.
+ * @param stateCallback A callback called on the supplied {@link Executor} that will contain the
+ * registration state of the IMS service, which will be one of the
+ * following: {@link #REGISTRATION_STATE_NOT_REGISTERED},
+ * {@link #REGISTRATION_STATE_REGISTERING}, or
+ * {@link #REGISTRATION_STATE_REGISTERED}.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- void getRegistrationState(@NonNull @ImsRegistrationState Consumer<Integer> stateCallback,
- @NonNull @CallbackExecutor Executor executor);
+ void getRegistrationState(@NonNull @CallbackExecutor Executor executor,
+ @NonNull @ImsRegistrationState Consumer<Integer> stateCallback);
/**
* Gets the Transport Type associated with the current IMS registration.
- * @param transportTypeCallback The transport type associated with the current IMS registration,
- * which will be one of following:
- * {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN},
- * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, or
- * {@link AccessNetworkConstants#TRANSPORT_TYPE_INVALID}.
* @param executor The {@link Executor} that will be used to call the transportTypeCallback.
+ * @param transportTypeCallback The transport type associated with the current IMS registration,
+ * which will be one of following:
+ * {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN},
+ * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, or
+ * {@link AccessNetworkConstants#TRANSPORT_TYPE_INVALID}.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
void getRegistrationTransportType(
- @NonNull @AccessNetworkConstants.TransportType Consumer<Integer> transportTypeCallback,
- @NonNull @CallbackExecutor Executor executor);
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull @AccessNetworkConstants.TransportType Consumer<Integer> transportTypeCallback);
}
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
new file mode 100644
index 000000000000..b379bd0cd748
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.telephony.ims.aidl;
+
+import android.net.Uri;
+import android.telephony.ims.aidl.IImsCapabilityCallback;
+import android.telephony.ims.aidl.IRcsUceControllerCallback;
+
+/**
+ * Interface used to interact with the Telephony IMS.
+ *
+ * {@hide}
+ */
+interface IImsRcsController {
+ void registerRcsAvailabilityCallback(IImsCapabilityCallback c);
+ void unregisterRcsAvailabilityCallback(IImsCapabilityCallback c);
+ boolean isCapable(int subId, int capability);
+ boolean isAvailable(int subId, int capability);
+
+ // ImsUceAdapter specific
+ void requestCapabilities(int subId, in List<Uri> contactNumbers, IRcsUceControllerCallback c);
+ int getUcePublishState(int subId);
+ boolean isUceSettingEnabled(int subId);
+ void setUceSettingEnabled(int subId, boolean isEnabled);
+}
diff --git a/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl b/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl
new file mode 100644
index 000000000000..5975930d5cfa
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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.telephony.ims.aidl;
+
+import android.telephony.ims.RcsContactUceCapability;
+
+/**
+ * Provides interface for RCS UCE when receive a change.
+ *
+ * {@hide}
+ */
+oneway interface IRcsUceControllerCallback {
+ void onCapabilitiesReceived(in List<RcsContactUceCapability> contactCapabilities);
+ void onError(int errorCode);
+}
diff --git a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
index 87a5094a95f3..1918bcb00733 100644
--- a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
+++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
@@ -18,6 +18,7 @@ package android.telephony.ims.feature;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -33,6 +34,7 @@ import java.util.Set;
* {@hide}
*/
@SystemApi
+@TestApi
public final class CapabilityChangeRequest implements Parcelable {
/**
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index 356288047e15..72390d070337 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -19,6 +19,7 @@ package android.telephony.ims.feature;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.content.Context;
import android.os.IInterface;
import android.os.RemoteCallbackList;
@@ -43,6 +44,7 @@ import java.util.Map;
* @hide
*/
@SystemApi
+@TestApi
public abstract class ImsFeature {
private static final String LOG_TAG = "ImsFeature";
@@ -212,6 +214,7 @@ public abstract class ImsFeature {
// Not Actually deprecated, but we need to remove it from the @SystemApi surface.
@Deprecated
@SystemApi // SystemApi only because it was leaked through type usage in a previous release.
+ @TestApi
public static class Capabilities {
/** @deprecated Use getters and accessors instead. */
// Not actually deprecated, but we need to remove it from the @SystemApi surface eventually.
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index 8b27b6fc4bfd..56c87710244c 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Bundle;
import android.os.Message;
import android.os.RemoteException;
@@ -54,6 +55,7 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
+@TestApi
public class MmTelFeature extends ImsFeature {
private static final String LOG_TAG = "MmTelFeature";
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index f69b434eb120..119f890bcb7b 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -20,6 +20,7 @@ import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.net.Uri;
import android.os.Binder;
import android.os.RemoteException;
@@ -49,6 +50,7 @@ import java.util.concurrent.Executor;
* @hide
*/
@SystemApi
+@TestApi
public class RcsFeature extends ImsFeature {
private static final String LOG_TAG = "RcsFeature";
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index da6a7a60c3b3..f4367da4a4dc 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -17,19 +17,19 @@
package android.telephony.ims.stub;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Message;
import android.os.RemoteException;
-import android.telephony.ims.ImsCallSessionListener;
-import android.telephony.ims.aidl.IImsCallSessionListener;
-
import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.ImsCallSession;
+import android.telephony.ims.ImsCallSessionListener;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ImsStreamMediaProfile;
-import android.telephony.ims.ImsCallSession;
-import com.android.ims.internal.IImsCallSession;
-import com.android.ims.internal.IImsVideoCallProvider;
import android.telephony.ims.ImsVideoCallProvider;
+import android.telephony.ims.aidl.IImsCallSessionListener;
+import com.android.ims.internal.IImsCallSession;
+import com.android.ims.internal.IImsVideoCallProvider;
/**
* Base implementation of IImsCallSession, which implements stub versions of the methods available.
*
@@ -38,6 +38,7 @@ import android.telephony.ims.ImsVideoCallProvider;
* @hide
*/
@SystemApi
+@TestApi
// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
// will break other implementations of ImsCallSession maintained by other ImsServices.
public class ImsCallSessionImplBase implements AutoCloseable {
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index 3e135cc9f048..4c0de7f9c1b7 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -18,6 +18,7 @@ package android.telephony.ims.stub;
import android.annotation.IntDef;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.content.Context;
import android.os.PersistableBundle;
import android.os.RemoteCallbackList;
@@ -48,6 +49,7 @@ import java.util.HashMap;
* @hide
*/
@SystemApi
+@TestApi
public class ImsConfigImplBase {
private static final String TAG = "ImsConfigImplBase";
diff --git a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
index 06c35eaec6dd..4a3a2eaf4225 100644
--- a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
@@ -17,6 +17,7 @@
package android.telephony.ims.stub;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.RemoteException;
import android.util.Log;
@@ -33,6 +34,7 @@ import com.android.ims.internal.IImsEcbmListener;
* @hide
*/
@SystemApi
+@TestApi
public class ImsEcbmImplBase {
private static final String TAG = "ImsEcbmImplBase";
diff --git a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
index cd9ebbf38e35..4e7307e2fa0c 100644
--- a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
+++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
@@ -19,6 +19,7 @@ package android.telephony.ims.stub;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.ims.feature.ImsFeature;
@@ -35,6 +36,7 @@ import java.util.Set;
* @hide
*/
@SystemApi
+@TestApi
public final class ImsFeatureConfiguration implements Parcelable {
public static final class FeatureSlotPair {
diff --git a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
index ce2d89a8d809..0ae5bba5d722 100644
--- a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
@@ -17,10 +17,11 @@
package android.telephony.ims.stub;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.RemoteException;
+import android.telephony.ims.ImsExternalCallState;
import android.util.Log;
-import android.telephony.ims.ImsExternalCallState;
import com.android.ims.internal.IImsExternalCallStateListener;
import com.android.ims.internal.IImsMultiEndpoint;
@@ -37,6 +38,7 @@ import java.util.List;
* @hide
*/
@SystemApi
+@TestApi
public class ImsMultiEndpointImplBase {
private static final String TAG = "MultiEndpointImplBase";
diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
index b455c2eff803..c0f16e5f9fbc 100644
--- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
@@ -18,6 +18,7 @@ package android.telephony.ims.stub;
import android.annotation.IntDef;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.net.Uri;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -38,6 +39,7 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
+@TestApi
public class ImsRegistrationImplBase {
private static final String LOG_TAG = "ImsRegistrationImplBase";
diff --git a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
index 36ece958d501..ce9a73a21657 100644
--- a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
@@ -19,6 +19,7 @@ package android.telephony.ims.stub;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.RemoteException;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
@@ -37,6 +38,7 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
+@TestApi
public class ImsSmsImplBase {
private static final String LOG_TAG = "SmsImplBase";
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
index fcd7faf73bb8..feac3c2ebfde 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
@@ -17,6 +17,7 @@
package android.telephony.ims.stub;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.ims.ImsUtListener;
@@ -33,6 +34,7 @@ import com.android.ims.internal.IImsUtListener;
// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
// will break other implementations of ImsUt maintained by other ImsServices.
@SystemApi
+@TestApi
public class ImsUtImplBase {
private IImsUt.Stub mServiceImpl = new IImsUt.Stub() {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
index c3d490a6d5cf..5766287d6691 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
@@ -25,17 +25,17 @@ import static android.telephony.SmsCbEtwsInfo.ETWS_WARNING_TYPE_TSUNAMI;
import android.annotation.NonNull;
import android.content.Context;
import android.content.res.Resources;
+import android.telephony.CbGeoUtils;
+import android.telephony.CbGeoUtils.Circle;
+import android.telephony.CbGeoUtils.Geometry;
+import android.telephony.CbGeoUtils.LatLng;
+import android.telephony.CbGeoUtils.Polygon;
import android.telephony.SmsCbLocation;
import android.telephony.SmsCbMessage;
import android.util.Pair;
import android.util.Slog;
import com.android.internal.R;
-import com.android.internal.telephony.CbGeoUtils;
-import com.android.internal.telephony.CbGeoUtils.Circle;
-import com.android.internal.telephony.CbGeoUtils.Geometry;
-import com.android.internal.telephony.CbGeoUtils.LatLng;
-import com.android.internal.telephony.CbGeoUtils.Polygon;
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.SmsConstants;
import com.android.internal.telephony.gsm.GsmSmsCbMessage.GeoFencingTriggerMessage.CellBroadcastIdentity;
diff --git a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
index ead4a28beff4..74aaec1eee34 100644
--- a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
+++ b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
@@ -108,13 +108,18 @@ public class BootImageProfileTest implements IDeviceTest {
// Test the profile contents contain common methods for core-oj that would normally be AOT
// compiled.
res = mTestDevice.executeShellCommand("profman --dump-classes-and-methods --profile-file="
- + SYSTEM_SERVER_PROFILE + " --apk=/apex/com.android.art/javalib/core-oj.jar");
+ + SYSTEM_SERVER_PROFILE + " --apk=/apex/com.android.art/javalib/core-oj.jar"
+ + " --apk=/system/framework/services.jar");
boolean sawObjectInit = false;
+ boolean sawPmInit = false;
for (String line : res.split("\n")) {
if (line.contains("Ljava/lang/Object;-><init>()V")) {
sawObjectInit = true;
+ } else if (line.contains("Lcom/android/server/pm/PackageManagerService;-><init>")) {
+ sawPmInit = true;
}
}
assertTrue("Did not see Object.<init> in " + res, sawObjectInit);
+ assertTrue("Did not see PackageManagerService.<init> in " + res, sawPmInit);
}
}
diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
index 7d88161a2805..176c7a0ada7b 100644
--- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
@@ -32,7 +32,7 @@ public class HierrarchicalDataClassBase implements Parcelable {
- // Code below generated by codegen v1.0.12.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -98,8 +98,8 @@ public class HierrarchicalDataClassBase implements Parcelable {
};
@DataClass.Generated(
- time = 1572655992854L,
- codegenVersion = "1.0.12",
+ time = 1573006405823L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java",
inputSignatures = "private int mBaseData\nclass HierrarchicalDataClassBase extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genSetters=true)")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
index c930ce535ab6..e348c77c0ac6 100644
--- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
@@ -46,7 +46,7 @@ public class HierrarchicalDataClassChild extends HierrarchicalDataClassBase {
- // Code below generated by codegen v1.0.12.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -120,8 +120,8 @@ public class HierrarchicalDataClassChild extends HierrarchicalDataClassBase {
};
@DataClass.Generated(
- time = 1572655993858L,
- codegenVersion = "1.0.12",
+ time = 1573006406833L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java",
inputSignatures = "private @android.annotation.NonNull java.lang.String mChildData\nclass HierrarchicalDataClassChild extends com.android.codegentest.HierrarchicalDataClassBase implements []\n@com.android.internal.util.DataClass(genParcelable=true, genConstructor=false, genSetters=true)")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
index 368a5c3a81e8..112d3df02280 100644
--- a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
@@ -19,6 +19,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.ArrayMap;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -52,7 +53,8 @@ public class ParcelAllTheThingsDataClass implements Parcelable {
- // Code below generated by codegen v1.0.12.
+
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -410,8 +412,8 @@ public class ParcelAllTheThingsDataClass implements Parcelable {
}
@DataClass.Generated(
- time = 1572655991821L,
- codegenVersion = "1.0.12",
+ time = 1573006404728L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java",
inputSignatures = " @android.annotation.NonNull java.lang.String[] mStringArray\n @android.annotation.NonNull int[] mIntArray\n @android.annotation.NonNull java.util.List<java.lang.String> mStringList\n @android.annotation.NonNull java.util.Map<java.lang.String,com.android.codegentest.SampleWithCustomBuilder> mMap\n @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.String> mStringMap\n @android.annotation.NonNull android.util.SparseArray<com.android.codegentest.SampleWithCustomBuilder> mSparseArray\n @android.annotation.NonNull android.util.SparseIntArray mSparseIntArray\n @java.lang.SuppressWarnings({\"WeakerAccess\"}) @android.annotation.Nullable java.lang.Boolean mNullableBoolean\nclass ParcelAllTheThingsDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
index 9d52287d631e..0fdcf5918c81 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
@@ -342,7 +342,7 @@ public final class SampleDataClass implements Parcelable {
- // Code below generated by codegen v1.0.12.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -1872,8 +1872,8 @@ public final class SampleDataClass implements Parcelable {
}
@DataClass.Generated(
- time = 1572655989589L,
- codegenVersion = "1.0.12",
+ time = 1573006402566L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleDataClass.java",
inputSignatures = "public static final java.lang.String STATE_NAME_UNDEFINED\npublic static final java.lang.String STATE_NAME_ON\npublic static final java.lang.String STATE_NAME_OFF\npublic static final int STATE_UNDEFINED\npublic static final int STATE_ON\npublic static final int STATE_OFF\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_AUGMENTED_REQUEST\nprivate int mNum\nprivate int mNum2\nprivate int mNum4\nprivate @android.annotation.Nullable java.lang.String mName\nprivate @android.annotation.NonNull java.lang.String mName2\nprivate @android.annotation.NonNull java.lang.String mName4\nprivate @android.annotation.Nullable android.view.accessibility.AccessibilityNodeInfo mOtherParcelable\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.codegentest.MyDateParcelling.class) @android.annotation.NonNull java.util.Date mDate\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForPattern.class) @android.annotation.NonNull java.util.regex.Pattern mPattern\nprivate @android.annotation.NonNull java.util.List<android.net.LinkAddress> mLinkAddresses2\nprivate @com.android.internal.util.DataClass.PluralOf(\"linkAddress\") @android.annotation.NonNull java.util.ArrayList<android.net.LinkAddress> mLinkAddresses\nprivate @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses4\nprivate @com.android.codegentest.SampleDataClass.StateName @android.annotation.NonNull java.lang.String mStateName\nprivate @com.android.codegentest.SampleDataClass.RequestFlags int mFlags\nprivate @com.android.codegentest.SampleDataClass.State int mState\npublic @android.annotation.NonNull java.lang.CharSequence charSeq\nprivate final @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses5\nprivate transient android.net.LinkAddress[] mLinkAddresses6\ntransient int[] mTmpStorage\nprivate @android.annotation.StringRes int mStringRes\nprivate @android.annotation.IntRange(from=0L, to=6L) int mDayOfWeek\nprivate @android.annotation.Size(2L) @android.annotation.NonNull @com.android.internal.util.DataClass.Each @android.annotation.FloatRange(from=0.0) float[] mCoords\nprivate static java.lang.String defaultName4()\nprivate int[] lazyInitTmpStorage()\npublic android.net.LinkAddress[] getLinkAddresses4()\nprivate boolean patternEquals(java.util.regex.Pattern)\nprivate int patternHashCode()\nprivate void onConstructed()\npublic void dump(java.io.PrintWriter)\nclass SampleDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genConstructor=true, genEqualsHashCode=true, genToString=true, genForEachField=true, genSetters=true)")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
index cef32d1051df..cab477dafae9 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
@@ -85,7 +85,7 @@ public class SampleWithCustomBuilder implements Parcelable {
- // Code below generated by codegen v1.0.12.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -253,8 +253,8 @@ public class SampleWithCustomBuilder implements Parcelable {
}
@DataClass.Generated(
- time = 1572655990725L,
- codegenVersion = "1.0.12",
+ time = 1573006403628L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java",
inputSignatures = " long delayAmount\n @android.annotation.NonNull java.util.concurrent.TimeUnit delayUnit\n long creationTimestamp\nprivate static java.util.concurrent.TimeUnit unparcelDelayUnit(android.os.Parcel)\nprivate void parcelDelayUnit(android.os.Parcel,int)\nclass SampleWithCustomBuilder extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)\nabstract com.android.codegentest.SampleWithCustomBuilder.Builder setDelayAmount(long)\npublic abstract com.android.codegentest.SampleWithCustomBuilder.Builder setDelayUnit(java.util.concurrent.TimeUnit)\npublic com.android.codegentest.SampleWithCustomBuilder.Builder setDelay(long,java.util.concurrent.TimeUnit)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java b/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
index 27055f6a4df8..6190085a4d82 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
@@ -36,7 +36,7 @@ public class SampleWithNestedDataClasses {
- // Code below generated by codegen v1.0.12.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -135,8 +135,8 @@ public class SampleWithNestedDataClasses {
};
@DataClass.Generated(
- time = 1572655995915L,
- codegenVersion = "1.0.12",
+ time = 1573006408903L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java",
inputSignatures = " @android.annotation.NonNull java.lang.String mBar\nclass NestedDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
@Deprecated
@@ -160,7 +160,7 @@ public class SampleWithNestedDataClasses {
- // Code below generated by codegen v1.0.12.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -259,8 +259,8 @@ public class SampleWithNestedDataClasses {
};
@DataClass.Generated(
- time = 1572655995924L,
- codegenVersion = "1.0.12",
+ time = 1573006408912L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java",
inputSignatures = " @android.annotation.NonNull long mBaz2\nclass NestedDataClass3 extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
@Deprecated
@@ -274,7 +274,7 @@ public class SampleWithNestedDataClasses {
- // Code below generated by codegen v1.0.12.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -373,8 +373,8 @@ public class SampleWithNestedDataClasses {
};
@DataClass.Generated(
- time = 1572655995930L,
- codegenVersion = "1.0.12",
+ time = 1573006408917L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java",
inputSignatures = " @android.annotation.NonNull java.lang.String mBaz\nclass NestedDataClass2 extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
@Deprecated
diff --git a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
index 4bfec895fdcb..5a960d7dd002 100644
--- a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
+++ b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
@@ -51,7 +51,7 @@ public class StaleDataclassDetectorFalsePositivesTest {
- // Code below generated by codegen v1.0.12.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -65,8 +65,8 @@ public class StaleDataclassDetectorFalsePositivesTest {
@DataClass.Generated(
- time = 1572655994865L,
- codegenVersion = "1.0.12",
+ time = 1573006407900L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java",
inputSignatures = "public @android.annotation.NonNull java.lang.String someMethod(int)\nclass StaleDataclassDetectorFalsePositivesTest extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=false)")
@Deprecated
diff --git a/tests/Gating/Android.bp b/tests/Gating/Android.bp
new file mode 100644
index 000000000000..b6c00948f5f3
--- /dev/null
+++ b/tests/Gating/Android.bp
@@ -0,0 +1,17 @@
+android_test {
+ name: "Gating",
+ // Only compile source java files in this apk.
+ srcs: ["src/**/*.java"],
+ certificate: "platform",
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+ static_libs: [
+ "junit",
+ "android-support-test",
+ "mockito-target-minus-junit4",
+ "truth-prebuilt",
+ "platform_compat-test-rules"
+ ],
+}
diff --git a/tests/Gating/AndroidManifest.xml b/tests/Gating/AndroidManifest.xml
new file mode 100644
index 000000000000..7f14b83fbc75
--- /dev/null
+++ b/tests/Gating/AndroidManifest.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.tests.gating">
+ <application android:label="GatingTest">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.tests.gating"/>
+</manifest>
diff --git a/tests/Gating/AndroidTest.xml b/tests/Gating/AndroidTest.xml
new file mode 100644
index 000000000000..730e74a6d337
--- /dev/null
+++ b/tests/Gating/AndroidTest.xml
@@ -0,0 +1,30 @@
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Test compatibility change gating.">
+ <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="Gating.apk"/>
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
+ <option name="test-suite-tag" value="apct"/>
+ <option name="test-tag" value="Gating"/>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.tests.gating"/>
+ <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/tests/Gating/src/com/android/compat/testing/DummyApi.java b/tests/Gating/src/com/android/compat/testing/DummyApi.java
new file mode 100644
index 000000000000..25106f91cb58
--- /dev/null
+++ b/tests/Gating/src/com/android/compat/testing/DummyApi.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compat.testing;
+
+import android.compat.Compatibility;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.compat.IPlatformCompat;
+
+/**
+ * This is a dummy API to test gating
+ *
+ * @hide
+ */
+public class DummyApi {
+
+ public static final long CHANGE_ID = 666013;
+ public static final long CHANGE_ID_1 = 666014;
+ public static final long CHANGE_ID_2 = 666015;
+ public static final long CHANGE_SYSTEM_SERVER = 666016;
+
+ /**
+ * Dummy method
+ * @return "A" if change is enabled, "B" otherwise.
+ */
+ public static String dummyFunc() {
+ if (Compatibility.isChangeEnabled(CHANGE_ID)) {
+ return "A";
+ }
+ return "B";
+ }
+
+ /**
+ * Dummy combined method
+ * @return "0" if {@link CHANGE_ID_1} is disabled and {@link CHANGE_ID_2} is disabled,
+ "1" if {@link CHANGE_ID_1} is disabled and {@link CHANGE_ID_2} is enabled,
+ "2" if {@link CHANGE_ID_1} is enabled and {@link CHANGE_ID_2} is disabled,
+ "3" if {@link CHANGE_ID_1} is enabled and {@link CHANGE_ID_2} is enabled.
+ */
+ public static String dummyCombinedFunc() {
+ if (!Compatibility.isChangeEnabled(CHANGE_ID_1)
+ && !Compatibility.isChangeEnabled(CHANGE_ID_2)) {
+ return "0";
+ } else if (!Compatibility.isChangeEnabled(CHANGE_ID_1)
+ && Compatibility.isChangeEnabled(CHANGE_ID_2)) {
+ return "1";
+ } else if (Compatibility.isChangeEnabled(CHANGE_ID_1)
+ && !Compatibility.isChangeEnabled(CHANGE_ID_2)) {
+ return "2";
+ }
+ return "3";
+ }
+
+ /**
+ * Dummy api using system server API.
+ */
+ public static String dummySystemServer(Context context) {
+ IPlatformCompat platformCompat = IPlatformCompat.Stub
+ .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
+ if (platformCompat == null) {
+ throw new RuntimeException("Could not obtain IPlatformCompat instance!");
+ }
+ String packageName = context.getPackageName();
+ try {
+ if (platformCompat.isChangeEnabledByPackageName(CHANGE_SYSTEM_SERVER, packageName,
+ context.getUserId())) {
+ return "True";
+ } else {
+ return "False";
+ }
+ } catch (RemoteException e) {
+ throw new RuntimeException("Could not get change value!", e);
+ }
+ }
+}
diff --git a/tests/Gating/src/com/android/tests/gating/GatingTest.java b/tests/Gating/src/com/android/tests/gating/GatingTest.java
new file mode 100644
index 000000000000..1e3f9ed29cc1
--- /dev/null
+++ b/tests/Gating/src/com/android/tests/gating/GatingTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.tests.gating;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.compat.testing.CompatChangeRule;
+import android.compat.testing.CompatChangeRule.DisableCompatChanges;
+import android.compat.testing.CompatChangeRule.EnableCompatChanges;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.compat.testing.DummyApi;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for platform compatibility change gating.
+ */
+@RunWith(AndroidJUnit4.class)
+public class GatingTest {
+
+ @Rule
+ public TestRule compatChangeRule = new CompatChangeRule();
+
+ @Test
+ @EnableCompatChanges({DummyApi.CHANGE_ID})
+ public void testDummyGatingPositive() {
+ assertThat(DummyApi.dummyFunc()).isEqualTo("A");
+ }
+
+ @Test
+ @DisableCompatChanges({DummyApi.CHANGE_ID})
+ public void testDummyGatingNegative() {
+ assertThat(DummyApi.dummyFunc()).isEqualTo("B");
+ }
+
+ @Test
+ @DisableCompatChanges({DummyApi.CHANGE_ID_1, DummyApi.CHANGE_ID_2})
+ public void testDummyGatingCombined0() {
+ assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("0");
+ }
+
+ @Test
+ @DisableCompatChanges({DummyApi.CHANGE_ID_1})
+ @EnableCompatChanges({DummyApi.CHANGE_ID_2})
+ public void testDummyGatingCombined1() {
+ assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("1");
+ }
+
+ @Test
+ @EnableCompatChanges({DummyApi.CHANGE_ID_1})
+ @DisableCompatChanges({DummyApi.CHANGE_ID_2})
+ public void testDummyGatingCombined2() {
+ assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("2");
+ }
+
+ @Test
+ @EnableCompatChanges({DummyApi.CHANGE_ID_1, DummyApi.CHANGE_ID_2})
+ public void testDummyGatingCombined3() {
+ assertThat(DummyApi.dummyCombinedFunc()).isEqualTo("3");
+ }
+
+ @Test
+ @EnableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER})
+ public void testDummyGatingPositiveSystemServer() {
+ assertThat(
+ DummyApi.dummySystemServer(InstrumentationRegistry.getTargetContext())).isEqualTo(
+ "True");
+ }
+
+ @Test
+ @DisableCompatChanges({DummyApi.CHANGE_SYSTEM_SERVER})
+ public void testDummyGatingNegativeSystemServer() {
+ assertThat(
+ DummyApi.dummySystemServer(InstrumentationRegistry.getTargetContext())).isEqualTo(
+ "False");
+ }
+}
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 8b0193092d27..06be5e2a0b9d 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -21,8 +21,6 @@ import static com.android.cts.rollback.lib.RollbackUtils.getUniqueRollbackInfoFo
import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assert.fail;
-
import android.Manifest;
import android.annotation.Nullable;
import android.content.ComponentName;
@@ -37,7 +35,7 @@ import android.os.ParcelFileDescriptor;
import android.provider.DeviceConfig;
import android.text.TextUtils;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.cts.install.lib.Install;
import com.android.cts.install.lib.InstallUtils;
@@ -155,10 +153,9 @@ public class StagedRollbackTest {
RollbackUtils.sendCrashBroadcast(TestApp.A, 1);
// We expect the device to be rebooted automatically. Wait for that to happen.
- Thread.sleep(30 * 1000);
-
- // Raise an error anyway if reboot didn't happen.
- fail("watchdog did not trigger reboot");
+ // This device method will fail and the host will catch the assertion.
+ // If reboot doesn't happen, the host will fail the assertion.
+ Thread.sleep(TimeUnit.SECONDS.toMillis(120));
}
/**
@@ -187,7 +184,7 @@ public class StagedRollbackTest {
@Test
public void testNativeWatchdogTriggersRollback_Phase1() throws Exception {
resetModuleMetadataPackage();
- Context context = InstrumentationRegistry.getContext();
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
PackageInfo metadataPackageInfo = context.getPackageManager().getPackageInfo(
MODULE_META_DATA_PACKAGE, 0);
String metadataApkPath = metadataPackageInfo.applicationInfo.sourceDir;
@@ -254,11 +251,11 @@ public class StagedRollbackTest {
@Test
public void testNetworkFailedRollback_Phase3() throws Exception {
- // Sleep for > health check deadline
+ // Sleep for > health check deadline (120s to trigger rollback + 120s to reboot)
// The device is expected to reboot during sleeping. This device method will fail and
// the host will catch the assertion. If reboot doesn't happen, the host will fail the
// assertion.
- Thread.sleep(TimeUnit.SECONDS.toMillis(120));
+ Thread.sleep(TimeUnit.SECONDS.toMillis(240));
}
@Test
@@ -271,7 +268,7 @@ public class StagedRollbackTest {
private static String getNetworkStackPackageName() {
Intent intent = new Intent(NETWORK_STACK_CONNECTOR_CLASS);
ComponentName comp = intent.resolveSystemService(
- InstrumentationRegistry.getContext().getPackageManager(), 0);
+ InstrumentationRegistry.getInstrumentation().getContext().getPackageManager(), 0);
return comp.getPackageName();
}
@@ -292,8 +289,8 @@ public class StagedRollbackTest {
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
int sessionId = Install.single(TestApp.A2).setStaged().setEnableRollback().commit();
- PackageInstaller pi = InstrumentationRegistry.getContext().getPackageManager()
- .getPackageInstaller();
+ PackageInstaller pi = InstrumentationRegistry.getInstrumentation().getContext()
+ .getPackageManager().getPackageInstaller();
pi.abandonSession(sessionId);
// Remove the first intent sender result, so that the next staged install session does not
@@ -349,8 +346,8 @@ public class StagedRollbackTest {
@Nullable
private static String getModuleMetadataPackageName() {
- String packageName = InstrumentationRegistry.getContext().getResources().getString(
- R.string.config_defaultModuleMetadataProvider);
+ String packageName = InstrumentationRegistry.getInstrumentation().getContext()
+ .getResources().getString(R.string.config_defaultModuleMetadataProvider);
if (TextUtils.isEmpty(packageName)) {
return null;
}
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 18a813d52b85..557d498ce8ee 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,11 +19,10 @@ package com.android.tests.rollback.host;
import static org.junit.Assert.assertTrue;
import static org.testng.Assert.assertThrows;
-import com.android.ddmlib.Log.LogLevel;
-import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -49,6 +48,11 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
phase));
}
+ @Before
+ public void setUp() throws Exception {
+ getDevice().reboot();
+ }
+
/**
* Tests watchdog triggered staged rollbacks involving only apks.
*/
@@ -57,17 +61,8 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
runPhase("testBadApkOnly_Phase1");
getDevice().reboot();
runPhase("testBadApkOnly_Phase2");
- try {
- // This is expected to fail due to the device being rebooted out
- // from underneath the test. If this fails for reasons other than
- // the device reboot, those failures should result in failure of
- // the testApkOnlyConfirmRollback phase.
- CLog.logAndDisplay(LogLevel.INFO, "testBadApkOnlyTriggerRollback is expected to fail");
- runPhase("testBadApkOnly_Phase3");
- } catch (AssertionError e) {
- // AssertionError is expected.
- }
+ assertThrows(AssertionError.class, () -> runPhase("testBadApkOnly_Phase3"));
getDevice().waitForDeviceAvailable();
runPhase("testBadApkOnly_Phase4");
diff --git a/tools/apilint/apilint b/tools/apilint/apilint
deleted file mode 100755
index e42857f1a190..000000000000
--- a/tools/apilint/apilint
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/bin/bash
-
-# 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.
-
-if [ "$1" == "--help" -o "$1" == "-h" ]; then
-echo "Usage: apilint [FILTERS...]"
-echo " Shows lint from currently open files (as diffed from HEAD), i.e. errors"
-echo " you will receive if you upload this CL."
-echo
-echo "Usage: apilint --all [FILTERS...]"
-echo " Shows all lint errors present in the current working directory, regardless"
-echo " of when they were added."
-echo
-echo "Usage: apilint --level API_LEVEL [FILTERS...]"
-echo " Shows lint as it stands in API_LEVEL"
-echo
-echo "Usage: apilint --shal SHA [FILTERS...]"
-echo " Shows lint from locally commited git change SHA."
-echo
-echo "Usage: apilint --unreleased [FILTERS...]"
-echo " Shows all lint errors in the current working directory directory added since"
-echo " the last released SDK version."
-echo
-echo "FILTERS"
-echo " List of class or package names by which to filter the results."
-echo
-exit
-fi
-
-if [ \( -z "$ANDROID_BUILD_TOP" \) \
- -a \( ! -f frameworks/base/api/current.txt \) \
- -a \( ! -f frameworks/base/api/system-current.txt \) \
- ]; then
- echo "apilint must be run either with ANDROID_BUILD_TOP set or from the" 1>&2
- echo "root of the android source tree" 1>&2
- exit 1
-fi
-
-if [ ${ANDROID_BUILD_TOP:0:1} != "/" ]; then
- echo "ANDROID_BUILD_TOP must be an absolute path, not: $ANDROID_BUILD_TOP" 1>&2
- exit 1
-fi
-
-if [ -z "$ANDROID_BUILD_TOP" ]; then
- ANDROID_BUILD_TOP=$(pwd)
-fi
-
-FW_BASE=$ANDROID_BUILD_TOP/frameworks/base
-
-MODE=open
-
-OPTIONS=$(getopt -n apilint -o "" -l "all,sha:,unreleased" -- "$@")
-
-[ $? -eq 0 ] || {
- exit 1
-}
-
-eval set -- "$OPTIONS"
-while true; do
- case "$1" in
- --all)
- MODE=all
- ;;
- --sha)
- shift; # The arg is next in position args
- MODE=sha
- SHA=$1
- ;;
- --unreleased)
- MODE=unreleased
- ;;
- --)
- shift
- break
- ;;
- esac
- shift
-done
-FILTERS=
-for var in "$@"
-do
- FILTERS="$FILTERS --filter $var"
-done
-
-if [ $MODE = "all" ]; then
- python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
- --title "SDK" \
- $FILTERS \
- $ANDROID_BUILD_TOP/frameworks/base/api/current.txt
- python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
- --title "SystemApi" \
- $FILTERS \
- --base-current $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \
- $ANDROID_BUILD_TOP/frameworks/base/api/system-current.txt
-elif [ $MODE = "open" ]; then
- python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
- --title "SDK" \
- $FILTERS \
- $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \
- <(cd $FW_BASE ; git show HEAD:api/current.txt)
- python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
- --title "SystemApi" \
- $FILTERS \
- --base-current $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \
- --base-previous <(cd $FW_BASE ; git show HEAD:api/current.txt) \
- $ANDROID_BUILD_TOP/frameworks/base/api/system-current.txt \
- <(cd $FW_BASE ; git show HEAD:api/system-current.txt)
-elif [ $MODE = "sha" ]; then
- python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
- --title "SDK" \
- $FILTERS \
- <(cd $FW_BASE ; git show $SHA:api/current.txt) \
- <(cd $FW_BASE ; git show $SHA^:api/current.txt)
- python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
- --title "SystemApi" \
- $FILTERS \
- --base-current <(cd $FW_BASE ; git show $SHA:api/current.txt) \
- --base-previous <(cd $FW_BASE ; git show $SHA^:api/current.txt) \
- <(cd $FW_BASE ; git show $SHA:api/system-current.txt) \
- <(cd $FW_BASE ; git show $SHA^:api/system-current.txt)
-elif [ $MODE = "unreleased" ]; then
- LAST_SDK=$(ls $ANDROID_BUILD_TOP/prebuilts/sdk | grep "^[0-9][0-9]*$" | sort -n | tail -n 1)
- python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
- --title "SDK" \
- $FILTERS \
- $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \
- $ANDROID_BUILD_TOP/prebuilts/sdk/$LAST_SDK/public/api/android.txt
- python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
- --title "SystemApi" \
- $FILTERS \
- --base-current $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \
- --base-previous $ANDROID_BUILD_TOP/prebuilts/sdk/$LAST_SDK/public/api/android.txt \
- $ANDROID_BUILD_TOP/frameworks/base/api/system-current.txt \
- $ANDROID_BUILD_TOP/prebuilts/sdk/$LAST_SDK/system/api/android.txt
-fi
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
deleted file mode 100644
index 912c1ad377c1..000000000000
--- a/tools/apilint/apilint.py
+++ /dev/null
@@ -1,2353 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the 'License');
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an 'AS IS' BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Enforces common Android public API design patterns. It ignores lint messages from
-a previous API level, if provided.
-
-Usage: apilint.py current.txt
-Usage: apilint.py current.txt previous.txt
-
-You can also splice in blame details like this:
-$ git blame api/current.txt -t -e > /tmp/currentblame.txt
-$ apilint.py /tmp/currentblame.txt previous.txt --no-color
-"""
-
-import re, sys, collections, traceback, argparse, itertools
-
-
-BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
-
-ALLOW_GOOGLE = False
-USE_COLOR = True
-
-def format(fg=None, bg=None, bright=False, bold=False, dim=False, reset=False):
- # manually derived from http://en.wikipedia.org/wiki/ANSI_escape_code#Codes
- if not USE_COLOR: return ""
- codes = []
- if reset: codes.append("0")
- else:
- if not fg is None: codes.append("3%d" % (fg))
- if not bg is None:
- if not bright: codes.append("4%d" % (bg))
- else: codes.append("10%d" % (bg))
- if bold: codes.append("1")
- elif dim: codes.append("2")
- else: codes.append("22")
- return "\033[%sm" % (";".join(codes))
-
-
-class Field():
- def __init__(self, clazz, line, raw, blame, sig_format = 1):
- self.clazz = clazz
- self.line = line
- self.raw = raw.strip(" {;")
- self.blame = blame
-
- if sig_format == 2:
- V2LineParser(raw).parse_into_field(self)
- elif sig_format == 1:
- # drop generics for now; may need multiple passes
- raw = re.sub("<[^<]+?>", "", raw)
- raw = re.sub("<[^<]+?>", "", raw)
-
- raw = raw.split()
- self.split = list(raw)
-
- for r in ["field", "volatile", "transient", "public", "protected", "static", "final", "deprecated"]:
- while r in raw: raw.remove(r)
-
- # ignore annotations for now
- raw = [ r for r in raw if not r.startswith("@") ]
-
- self.typ = raw[0]
- self.name = raw[1].strip(";")
- if len(raw) >= 4 and raw[2] == "=":
- self.value = raw[3].strip(';"')
- else:
- self.value = None
- self.annotations = []
-
- self.ident = "-".join((self.typ, self.name, self.value or ""))
-
- def __hash__(self):
- return hash(self.raw)
-
- def __repr__(self):
- return self.raw
-
-
-class Argument(object):
-
- __slots__ = ["type", "annotations", "name", "default"]
-
- def __init__(self, type):
- self.type = type
- self.annotations = []
- self.name = None
- self.default = None
-
-
-class Method():
- def __init__(self, clazz, line, raw, blame, sig_format = 1):
- self.clazz = clazz
- self.line = line
- self.raw = raw.strip(" {;")
- self.blame = blame
-
- if sig_format == 2:
- V2LineParser(raw).parse_into_method(self)
- elif sig_format == 1:
- # drop generics for now; may need multiple passes
- raw = re.sub("<[^<]+?>", "", raw)
- raw = re.sub("<[^<]+?>", "", raw)
-
- # handle each clause differently
- raw_prefix, raw_args, _, raw_throws = re.match(r"(.*?)\((.*?)\)( throws )?(.*?);$", raw).groups()
-
- # parse prefixes
- raw = re.split("[\s]+", raw_prefix)
- for r in ["", ";"]:
- while r in raw: raw.remove(r)
- self.split = list(raw)
-
- for r in ["method", "public", "protected", "static", "final", "deprecated", "abstract", "default", "operator", "synchronized"]:
- while r in raw: raw.remove(r)
-
- self.typ = raw[0]
- self.name = raw[1]
-
- # parse args
- self.detailed_args = []
- for arg in re.split(",\s*", raw_args):
- arg = re.split("\s", arg)
- # ignore annotations for now
- arg = [ a for a in arg if not a.startswith("@") ]
- if len(arg[0]) > 0:
- self.detailed_args.append(Argument(arg[0]))
-
- # parse throws
- self.throws = []
- for throw in re.split(",\s*", raw_throws):
- self.throws.append(throw)
-
- self.annotations = []
- else:
- raise ValueError("Unknown signature format: " + sig_format)
-
- self.args = map(lambda a: a.type, self.detailed_args)
- self.ident = "-".join((self.typ, self.name, "-".join(self.args)))
-
- def sig_matches(self, typ, name, args):
- return typ == self.typ and name == self.name and args == self.args
-
- def __hash__(self):
- return hash(self.raw)
-
- def __repr__(self):
- return self.raw
-
-
-class Class():
- def __init__(self, pkg, line, raw, blame, sig_format = 1):
- self.pkg = pkg
- self.line = line
- self.raw = raw.strip(" {;")
- self.blame = blame
- self.ctors = []
- self.fields = []
- self.methods = []
- self.annotations = []
-
- if sig_format == 2:
- V2LineParser(raw).parse_into_class(self)
- elif sig_format == 1:
- # drop generics for now; may need multiple passes
- raw = re.sub("<[^<]+?>", "", raw)
- raw = re.sub("<[^<]+?>", "", raw)
-
- raw = raw.split()
- self.split = list(raw)
- if "class" in raw:
- self.fullname = raw[raw.index("class")+1]
- elif "interface" in raw:
- self.fullname = raw[raw.index("interface")+1]
- elif "@interface" in raw:
- self.fullname = raw[raw.index("@interface")+1]
- else:
- raise ValueError("Funky class type %s" % (self.raw))
-
- if "extends" in raw:
- self.extends = raw[raw.index("extends")+1]
- else:
- self.extends = None
-
- if "implements" in raw:
- self.implements = raw[raw.index("implements")+1]
- self.implements_all = [self.implements]
- else:
- self.implements = None
- self.implements_all = []
- else:
- raise ValueError("Unknown signature format: " + sig_format)
-
- self.fullname = self.pkg.name + "." + self.fullname
- self.fullname_path = self.fullname.split(".")
-
- if self.extends is not None:
- self.extends_path = self.extends.split(".")
- else:
- self.extends_path = []
-
- self.name = self.fullname[self.fullname.rindex(".")+1:]
-
- def merge_from(self, other):
- self.ctors.extend(other.ctors)
- self.fields.extend(other.fields)
- self.methods.extend(other.methods)
-
- def __hash__(self):
- return hash((self.raw, tuple(self.ctors), tuple(self.fields), tuple(self.methods)))
-
- def __repr__(self):
- return self.raw
-
-
-class Package():
- NAME = re.compile("package(?: .*)? ([A-Za-z0-9.]+)")
-
- def __init__(self, line, raw, blame):
- self.line = line
- self.raw = raw.strip(" {;")
- self.blame = blame
-
- self.name = Package.NAME.match(raw).group(1)
- self.name_path = self.name.split(".")
-
- def __repr__(self):
- return self.raw
-
-class V2Tokenizer(object):
- __slots__ = ["raw"]
-
- SIGNATURE_PREFIX = "// Signature format: "
- DELIMITER = re.compile(r'\s+|[()@<>;,={}/"!?]|\[\]|\.\.\.')
- STRING_SPECIAL = re.compile(r'["\\]')
-
- def __init__(self, raw):
- self.raw = raw
-
- def tokenize(self):
- tokens = []
- current = 0
- raw = self.raw
- length = len(raw)
-
- while current < length:
- while current < length:
- start = current
- match = V2Tokenizer.DELIMITER.search(raw, start)
- if match is not None:
- match_start = match.start()
- if match_start == current:
- end = match.end()
- else:
- end = match_start
- else:
- end = length
-
- token = raw[start:end]
- current = end
-
- if token == "" or token[0] == " ":
- continue
- else:
- break
-
- if token == "@":
- if raw[start:start+11] == "@interface ":
- current = start + 11
- tokens.append("@interface")
- continue
- elif token == '/':
- if raw[start:start+2] == "//":
- current = length
- continue
- elif token == '"':
- current, string_token = self.tokenize_string(raw, length, current)
- tokens.append(token + string_token)
- continue
-
- tokens.append(token)
-
- return tokens
-
- def tokenize_string(self, raw, length, current):
- start = current
- end = length
- while start < end:
- match = V2Tokenizer.STRING_SPECIAL.search(raw, start)
- if match:
- if match.group() == '"':
- end = match.end()
- break
- elif match.group() == '\\':
- # ignore whatever is after the slash
- start += 2
- else:
- raise ValueError("Unexpected match: `%s`" % (match.group()))
- else:
- raise ValueError("Unexpected EOF tokenizing string: `%s`" % (raw[current - 1:],))
-
- token = raw[current:end]
- return end, token
-
-class V2LineParser(object):
- __slots__ = ["tokenized", "current", "len"]
-
- FIELD_KINDS = ("field", "property", "enum_constant")
- MODIFIERS = set("public protected internal private abstract default static final transient volatile synchronized native operator sealed strictfp infix inline suspend vararg".split())
- JAVA_LANG_TYPES = set("AbstractMethodError AbstractStringBuilder Appendable ArithmeticException ArrayIndexOutOfBoundsException ArrayStoreException AssertionError AutoCloseable Boolean BootstrapMethodError Byte Character CharSequence Class ClassCastException ClassCircularityError ClassFormatError ClassLoader ClassNotFoundException Cloneable CloneNotSupportedException Comparable Compiler Deprecated Double Enum EnumConstantNotPresentException Error Exception ExceptionInInitializerError Float FunctionalInterface IllegalAccessError IllegalAccessException IllegalArgumentException IllegalMonitorStateException IllegalStateException IllegalThreadStateException IncompatibleClassChangeError IndexOutOfBoundsException InheritableThreadLocal InstantiationError InstantiationException Integer InternalError InterruptedException Iterable LinkageError Long Math NegativeArraySizeException NoClassDefFoundError NoSuchFieldError NoSuchFieldException NoSuchMethodError NoSuchMethodException NullPointerException Number NumberFormatException Object OutOfMemoryError Override Package package-info.java Process ProcessBuilder ProcessEnvironment ProcessImpl Readable ReflectiveOperationException Runnable Runtime RuntimeException RuntimePermission SafeVarargs SecurityException SecurityManager Short StackOverflowError StackTraceElement StrictMath String StringBuffer StringBuilder StringIndexOutOfBoundsException SuppressWarnings System Thread ThreadDeath ThreadGroup ThreadLocal Throwable TypeNotPresentException UNIXProcess UnknownError UnsatisfiedLinkError UnsupportedClassVersionError UnsupportedOperationException VerifyError VirtualMachineError Void".split())
-
- def __init__(self, raw):
- self.tokenized = V2Tokenizer(raw).tokenize()
- self.current = 0
- self.len = len(self.tokenized)
-
- def parse_into_method(self, method):
- method.split = []
- kind = self.parse_one_of("ctor", "method")
- method.split.append(kind)
- method.annotations = self.parse_annotations()
- method.split.extend(self.parse_modifiers())
- self.parse_matching_paren("<", ">")
- if "@Deprecated" in method.annotations:
- method.split.append("deprecated")
- if kind == "ctor":
- method.typ = "ctor"
- else:
- method.typ = self.parse_type()
- method.split.append(method.typ)
- method.name = self.parse_name()
- method.split.append(method.name)
- self.parse_token("(")
- method.detailed_args = self.parse_args()
- self.parse_token(")")
- method.throws = self.parse_throws()
- if "@interface" in method.clazz.split:
- self.parse_annotation_default()
- self.parse_token(";")
- self.parse_eof()
-
- def parse_into_class(self, clazz):
- clazz.split = []
- clazz.annotations = self.parse_annotations()
- if "@Deprecated" in clazz.annotations:
- clazz.split.append("deprecated")
- clazz.split.extend(self.parse_modifiers())
- kind = self.parse_one_of("class", "interface", "@interface", "enum")
- if kind == "enum":
- # enums are implicitly final
- clazz.split.append("final")
- clazz.split.append(kind)
- clazz.fullname = self.parse_name()
- self.parse_matching_paren("<", ">")
- extends = self.parse_extends()
- clazz.extends = extends[0] if extends else None
- clazz.implements_all = self.parse_implements()
- # The checks assume that interfaces are always found in implements, which isn't true for
- # subinterfaces.
- if not clazz.implements_all and "interface" in clazz.split:
- clazz.implements_all = [clazz.extends]
- clazz.implements = clazz.implements_all[0] if clazz.implements_all else None
- self.parse_token("{")
- self.parse_eof()
-
- def parse_into_field(self, field):
- kind = self.parse_one_of(*V2LineParser.FIELD_KINDS)
- field.split = [kind]
- field.annotations = self.parse_annotations()
- if "@Deprecated" in field.annotations:
- field.split.append("deprecated")
- field.split.extend(self.parse_modifiers())
- field.typ = self.parse_type()
- field.split.append(field.typ)
- field.name = self.parse_name()
- field.split.append(field.name)
- if self.parse_if("="):
- field.value = self.parse_value_stripped()
- else:
- field.value = None
-
- self.parse_token(";")
- self.parse_eof()
-
- def lookahead(self):
- return self.tokenized[self.current]
-
- def parse_one_of(self, *options):
- found = self.lookahead()
- if found not in options:
- raise ValueError("Parsing failed, expected one of `%s` but found `%s` in %s" % (options, found, repr(self.tokenized)))
- return self.parse_token()
-
- def parse_token(self, tok = None):
- found = self.lookahead()
- if tok is not None and found != tok:
- raise ValueError("Parsing failed, expected `%s` but found `%s` in %s" % (tok, found, repr(self.tokenized)))
- self.current += 1
- return found
-
- def eof(self):
- return self.current == self.len
-
- def parse_eof(self):
- if not self.eof():
- raise ValueError("Parsing failed, expected EOF, but %s has not been parsed in %s" % (self.tokenized[self.current:], self.tokenized))
-
- def parse_if(self, tok):
- if not self.eof() and self.lookahead() == tok:
- self.parse_token()
- return True
- return False
-
- def parse_annotations(self):
- ret = []
- while self.lookahead() == "@":
- ret.append(self.parse_annotation())
- return ret
-
- def parse_annotation(self):
- ret = self.parse_token("@") + self.parse_token()
- self.parse_matching_paren("(", ")")
- return ret
-
- def parse_matching_paren(self, open, close):
- start = self.current
- if not self.parse_if(open):
- return
- length = len(self.tokenized)
- count = 1
- while count > 0:
- if self.current == length:
- raise ValueError("Unexpected EOF looking for closing paren: `%s`" % (self.tokenized[start:],))
- t = self.parse_token()
- if t == open:
- count += 1
- elif t == close:
- count -= 1
- return self.tokenized[start:self.current]
-
- def parse_modifiers(self):
- ret = []
- while self.lookahead() in V2LineParser.MODIFIERS:
- ret.append(self.parse_token())
- return ret
-
- def parse_kotlin_nullability(self):
- t = self.lookahead()
- if t == "?" or t == "!":
- return self.parse_token()
- return None
-
- def parse_type(self):
- self.parse_annotations()
- type = self.parse_token()
- if type[-1] == '.':
- self.parse_annotations()
- type += self.parse_token()
- if type in V2LineParser.JAVA_LANG_TYPES:
- type = "java.lang." + type
- self.parse_matching_paren("<", ">")
- while True:
- t = self.lookahead()
- if t == "@":
- self.parse_annotation()
- elif t == "[]":
- type += self.parse_token()
- elif self.parse_kotlin_nullability() is not None:
- pass # discard nullability for now
- else:
- break
- return type
-
- def parse_arg_type(self):
- type = self.parse_type()
- if self.parse_if("..."):
- type += "..."
- self.parse_kotlin_nullability() # discard nullability for now
- return type
-
- def parse_name(self):
- return self.parse_token()
-
- def parse_args(self):
- args = []
- if self.lookahead() == ")":
- return args
-
- while True:
- args.append(self.parse_arg())
- if self.lookahead() == ")":
- return args
- self.parse_token(",")
-
- def parse_arg(self):
- self.parse_if("vararg") # kotlin vararg
- annotations = self.parse_annotations()
- arg = Argument(self.parse_arg_type())
- arg.annotations = annotations
- l = self.lookahead()
- if l != "," and l != ")":
- if self.lookahead() != '=':
- arg.name = self.parse_token() # kotlin argument name
- if self.parse_if('='): # kotlin default value
- arg.default = self.parse_expression()
- return arg
-
- def parse_expression(self):
- while not self.lookahead() in [')', ',', ';']:
- (self.parse_matching_paren('(', ')') or
- self.parse_matching_paren('{', '}') or
- self.parse_token())
-
- def parse_throws(self):
- ret = []
- if self.parse_if("throws"):
- ret.append(self.parse_type())
- while self.parse_if(","):
- ret.append(self.parse_type())
- return ret
-
- def parse_extends(self):
- if self.parse_if("extends"):
- return self.parse_space_delimited_type_list()
- return []
-
- def parse_implements(self):
- if self.parse_if("implements"):
- return self.parse_space_delimited_type_list()
- return []
-
- def parse_space_delimited_type_list(self, terminals = ["implements", "{"]):
- types = []
- while True:
- types.append(self.parse_type())
- if self.lookahead() in terminals:
- return types
-
- def parse_annotation_default(self):
- if self.parse_if("default"):
- self.parse_expression()
-
- def parse_value(self):
- if self.lookahead() == "{":
- return " ".join(self.parse_matching_paren("{", "}"))
- elif self.lookahead() == "(":
- return " ".join(self.parse_matching_paren("(", ")"))
- else:
- return self.parse_token()
-
- def parse_value_stripped(self):
- value = self.parse_value()
- if value[0] == '"':
- return value[1:-1]
- return value
-
-
-def _parse_stream(f, clazz_cb=None, base_f=None, out_classes_with_base=None,
- in_classes_with_base=[]):
- api = {}
- in_classes_with_base = _retry_iterator(in_classes_with_base)
-
- if base_f:
- base_classes = _retry_iterator(_parse_stream_to_generator(base_f))
- else:
- base_classes = []
-
- def handle_class(clazz):
- if clazz_cb:
- clazz_cb(clazz)
- else: # In callback mode, don't keep track of the full API
- api[clazz.fullname] = clazz
-
- def handle_missed_classes_with_base(clazz):
- for c in _yield_until_matching_class(in_classes_with_base, clazz):
- base_class = _skip_to_matching_class(base_classes, c)
- if base_class:
- handle_class(base_class)
-
- for clazz in _parse_stream_to_generator(f):
- # Before looking at clazz, let's see if there's some classes that were not present, but
- # may have an entry in the base stream.
- handle_missed_classes_with_base(clazz)
-
- base_class = _skip_to_matching_class(base_classes, clazz)
- if base_class:
- clazz.merge_from(base_class)
- if out_classes_with_base is not None:
- out_classes_with_base.append(clazz)
- handle_class(clazz)
-
- handle_missed_classes_with_base(None)
-
- return api
-
-def _parse_stream_to_generator(f):
- line = 0
- pkg = None
- clazz = None
- blame = None
- sig_format = 1
-
- re_blame = re.compile(r"^(\^?[a-z0-9]{7,}) \(<([^>]+)>.+?\) (.+?)$")
-
- field_prefixes = map(lambda kind: " %s" % (kind,), V2LineParser.FIELD_KINDS)
- def startsWithFieldPrefix(raw):
- for prefix in field_prefixes:
- if raw.startswith(prefix):
- return True
- return False
-
- for raw in f:
- line += 1
- raw = raw.rstrip()
- match = re_blame.match(raw)
- if match is not None:
- blame = match.groups()[0:2]
- if blame[0].startswith("^"): # Outside of blame range
- blame = None
- raw = match.groups()[2]
- else:
- blame = None
-
- if line == 1 and V2Tokenizer.SIGNATURE_PREFIX in raw:
- sig_format_string = raw[len(V2Tokenizer.SIGNATURE_PREFIX):]
- if sig_format_string in ["2.0", "3.0"]:
- sig_format = 2
- else:
- raise ValueError("Unknown format: %s" % (sig_format_string,))
- elif raw.startswith("package"):
- pkg = Package(line, raw, blame)
- elif raw.startswith(" ") and raw.endswith("{"):
- clazz = Class(pkg, line, raw, blame, sig_format=sig_format)
- elif raw.startswith(" ctor"):
- clazz.ctors.append(Method(clazz, line, raw, blame, sig_format=sig_format))
- elif raw.startswith(" method"):
- clazz.methods.append(Method(clazz, line, raw, blame, sig_format=sig_format))
- elif startsWithFieldPrefix(raw):
- clazz.fields.append(Field(clazz, line, raw, blame, sig_format=sig_format))
- elif raw.startswith(" }") and clazz:
- yield clazz
-
-def _retry_iterator(it):
- """Wraps an iterator, such that calling send(True) on it will redeliver the same element"""
- for e in it:
- while True:
- retry = yield e
- if not retry:
- break
- # send() was called, asking us to redeliver clazz on next(). Still need to yield
- # a dummy value to the send() first though.
- if (yield "Returning clazz on next()"):
- raise TypeError("send() must be followed by next(), not send()")
-
-def _skip_to_matching_class(classes, needle):
- """Takes a classes iterator and consumes entries until it returns the class we're looking for
-
- This relies on classes being sorted by package and class name."""
-
- for clazz in classes:
- if clazz.pkg.name < needle.pkg.name:
- # We haven't reached the right package yet
- continue
- if clazz.pkg.name == needle.pkg.name and clazz.fullname < needle.fullname:
- # We're in the right package, but not the right class yet
- continue
- if clazz.fullname == needle.fullname:
- return clazz
- # We ran past the right class. Send it back into the generator, then report failure.
- classes.send(clazz)
- return None
-
-def _yield_until_matching_class(classes, needle):
- """Takes a class iterator and yields entries it until it reaches the class we're looking for.
-
- This relies on classes being sorted by package and class name."""
-
- for clazz in classes:
- if needle is None:
- yield clazz
- elif clazz.pkg.name < needle.pkg.name:
- # We haven't reached the right package yet
- yield clazz
- elif clazz.pkg.name == needle.pkg.name and clazz.fullname < needle.fullname:
- # We're in the right package, but not the right class yet
- yield clazz
- elif clazz.fullname == needle.fullname:
- # Class found, abort.
- return
- else:
- # We ran past the right class. Send it back into the iterator, then abort.
- classes.send(clazz)
- return
-
-class Failure():
- def __init__(self, sig, clazz, detail, error, rule, msg):
- self.clazz = clazz
- self.sig = sig
- self.error = error
- self.rule = rule
- self.msg = msg
-
- if error:
- self.head = "Error %s" % (rule) if rule else "Error"
- dump = "%s%s:%s %s" % (format(fg=RED, bg=BLACK, bold=True), self.head, format(reset=True), msg)
- else:
- self.head = "Warning %s" % (rule) if rule else "Warning"
- dump = "%s%s:%s %s" % (format(fg=YELLOW, bg=BLACK, bold=True), self.head, format(reset=True), msg)
-
- self.line = clazz.line
- blame = clazz.blame
- if detail is not None:
- dump += "\n in " + repr(detail)
- self.line = detail.line
- blame = detail.blame
- dump += "\n in " + repr(clazz)
- dump += "\n in " + repr(clazz.pkg)
- dump += "\n at line " + repr(self.line)
- if blame is not None:
- dump += "\n last modified by %s in %s" % (blame[1], blame[0])
-
- self.dump = dump
-
- def __repr__(self):
- return self.dump
-
-
-failures = {}
-
-def _fail(clazz, detail, error, rule, msg):
- """Records an API failure to be processed later."""
- global failures
-
- sig = "%s-%s-%s" % (clazz.fullname, detail.ident if detail else None, msg)
- sig = sig.replace(" deprecated ", " ")
-
- failures[sig] = Failure(sig, clazz, detail, error, rule, msg)
-
-
-def warn(clazz, detail, rule, msg):
- _fail(clazz, detail, False, rule, msg)
-
-def error(clazz, detail, rule, msg):
- _fail(clazz, detail, True, rule, msg)
-
-
-noticed = {}
-
-def notice(clazz):
- global noticed
-
- noticed[clazz.fullname] = hash(clazz)
-
-
-verifiers = {}
-
-def verifier(f):
- verifiers[f.__name__] = f
- return f
-
-
-@verifier
-def verify_constants(clazz):
- """All static final constants must be FOO_NAME style."""
- if re.match("android\.R\.[a-z]+", clazz.fullname): return
- if clazz.fullname.startswith("android.os.Build"): return
- if clazz.fullname == "android.system.OsConstants": return
-
- req = ["java.lang.String","byte","short","int","long","float","double","boolean","char"]
- for f in clazz.fields:
- if "static" in f.split and "final" in f.split:
- if re.match("[A-Z0-9_]+", f.name) is None:
- error(clazz, f, "C2", "Constant field names must be FOO_NAME")
- if f.typ != "java.lang.String":
- if f.name.startswith("MIN_") or f.name.startswith("MAX_"):
- warn(clazz, f, "C8", "If min/max could change in future, make them dynamic methods")
- if f.typ in req and f.value is None:
- error(clazz, f, None, "All constants must be defined at compile time")
-
-@verifier
-def verify_enums(clazz):
- """Enums are bad, mmkay?"""
- if clazz.extends == "java.lang.Enum" or "enum" in clazz.split:
- error(clazz, None, "F5", "Enums are not allowed")
-
-@verifier
-def verify_class_names(clazz):
- """Try catching malformed class names like myMtp or MTPUser."""
- if clazz.fullname.startswith("android.opengl"): return
- if clazz.fullname.startswith("android.renderscript"): return
- if re.match("android\.R\.[a-z]+", clazz.fullname): return
-
- if re.search("[A-Z]{2,}", clazz.name) is not None:
- warn(clazz, None, "S1", "Class names with acronyms should be Mtp not MTP")
- if re.match("[^A-Z]", clazz.name):
- error(clazz, None, "S1", "Class must start with uppercase char")
- if clazz.name.endswith("Impl"):
- error(clazz, None, None, "Don't expose your implementation details")
-
-
-@verifier
-def verify_method_names(clazz):
- """Try catching malformed method names, like Foo() or getMTU()."""
- if clazz.fullname.startswith("android.opengl"): return
- if clazz.fullname.startswith("android.renderscript"): return
- if clazz.fullname == "android.system.OsConstants": return
-
- for m in clazz.methods:
- if re.search("[A-Z]{2,}", m.name) is not None:
- warn(clazz, m, "S1", "Method names with acronyms should be getMtu() instead of getMTU()")
- if re.match("[^a-z]", m.name):
- error(clazz, m, "S1", "Method name must start with lowercase char")
-
-
-@verifier
-def verify_callbacks(clazz):
- """Verify Callback classes.
- All methods must follow onFoo() naming style."""
- if clazz.fullname == "android.speech.tts.SynthesisCallback": return
-
- if clazz.name.endswith("Callbacks"):
- error(clazz, None, "L1", "Callback class names should be singular")
- if clazz.name.endswith("Observer"):
- warn(clazz, None, "L1", "Class should be named FooCallback")
-
- if clazz.name.endswith("Callback"):
- for m in clazz.methods:
- if not re.match("on[A-Z][a-z]*", m.name):
- error(clazz, m, "L1", "Callback method names must be onFoo() style")
-
-
-@verifier
-def verify_listeners(clazz):
- """Verify Listener classes.
- All Listener classes must be interface.
- All methods must follow onFoo() naming style.
- If only a single method, it must match class name:
- interface OnFooListener { void onFoo() }"""
-
- if clazz.name.endswith("Listener"):
- if "abstract" in clazz.split and "class" in clazz.split:
- error(clazz, None, "L1", "Listeners should be an interface, or otherwise renamed Callback")
-
- for m in clazz.methods:
- if not re.match("on[A-Z][a-z]*", m.name):
- error(clazz, m, "L1", "Listener method names must be onFoo() style")
-
- if len(clazz.methods) == 1 and clazz.name.startswith("On"):
- m = clazz.methods[0]
- if (m.name + "Listener").lower() != clazz.name.lower():
- error(clazz, m, "L1", "Single listener method name must match class name")
-
-
-@verifier
-def verify_actions(clazz):
- """Verify intent actions.
- All action names must be named ACTION_FOO.
- All action values must be scoped by package and match name:
- package android.foo {
- String ACTION_BAR = "android.foo.action.BAR";
- }"""
- for f in clazz.fields:
- if f.value is None: continue
- if f.name.startswith("EXTRA_"): continue
- if f.name == "SERVICE_INTERFACE" or f.name == "PROVIDER_INTERFACE": continue
- if "INTERACTION" in f.name: continue
-
- if "static" in f.split and "final" in f.split and f.typ == "java.lang.String":
- if "_ACTION" in f.name or "ACTION_" in f.name or ".action." in f.value.lower():
- if not f.name.startswith("ACTION_"):
- error(clazz, f, "C3", "Intent action constant name must be ACTION_FOO")
- else:
- if clazz.fullname == "android.content.Intent":
- prefix = "android.intent.action"
- elif clazz.fullname == "android.provider.Settings":
- prefix = "android.settings"
- elif clazz.fullname == "android.app.admin.DevicePolicyManager" or clazz.fullname == "android.app.admin.DeviceAdminReceiver":
- prefix = "android.app.action"
- else:
- prefix = clazz.pkg.name + ".action"
- expected = prefix + "." + f.name[7:]
- if f.value != expected:
- error(clazz, f, "C4", "Inconsistent action value; expected '%s'" % (expected))
-
-
-@verifier
-def verify_extras(clazz):
- """Verify intent extras.
- All extra names must be named EXTRA_FOO.
- All extra values must be scoped by package and match name:
- package android.foo {
- String EXTRA_BAR = "android.foo.extra.BAR";
- }"""
- if clazz.fullname == "android.app.Notification": return
- if clazz.fullname == "android.appwidget.AppWidgetManager": return
-
- for f in clazz.fields:
- if f.value is None: continue
- if f.name.startswith("ACTION_"): continue
-
- if "static" in f.split and "final" in f.split and f.typ == "java.lang.String":
- if "_EXTRA" in f.name or "EXTRA_" in f.name or ".extra" in f.value.lower():
- if not f.name.startswith("EXTRA_"):
- error(clazz, f, "C3", "Intent extra must be EXTRA_FOO")
- else:
- if clazz.pkg.name == "android.content" and clazz.name == "Intent":
- prefix = "android.intent.extra"
- elif clazz.pkg.name == "android.app.admin":
- prefix = "android.app.extra"
- else:
- prefix = clazz.pkg.name + ".extra"
- expected = prefix + "." + f.name[6:]
- if f.value != expected:
- error(clazz, f, "C4", "Inconsistent extra value; expected '%s'" % (expected))
-
-
-@verifier
-def verify_equals(clazz):
- """Verify that equals() and hashCode() must be overridden together."""
- eq = False
- hc = False
- for m in clazz.methods:
- if "static" in m.split: continue
- if m.sig_matches("boolean", "equals", ["java.lang.Object"]): eq = True
- if m.sig_matches("int", "hashCode", []): hc = True
- if eq != hc:
- error(clazz, None, "M8", "Must override both equals and hashCode; missing one")
-
-
-@verifier
-def verify_parcelable(clazz):
- """Verify that Parcelable objects aren't hiding required bits."""
- if clazz.implements == "android.os.Parcelable":
- creator = [ i for i in clazz.fields if i.name == "CREATOR" ]
- write = [ i for i in clazz.methods if i.name == "writeToParcel" ]
- describe = [ i for i in clazz.methods if i.name == "describeContents" ]
-
- if len(creator) == 0 or len(write) == 0 or len(describe) == 0:
- error(clazz, None, "FW3", "Parcelable requires CREATOR, writeToParcel, and describeContents; missing one")
-
- if "final" not in clazz.split:
- error(clazz, None, "FW8", "Parcelable classes must be final")
-
- for c in clazz.ctors:
- if c.args == ["android.os.Parcel"]:
- error(clazz, c, "FW3", "Parcelable inflation is exposed through CREATOR, not raw constructors")
-
-
-@verifier
-def verify_protected(clazz):
- """Verify that no protected methods or fields are allowed."""
- for m in clazz.methods:
- if m.name == "finalize": continue
- if "protected" in m.split:
- error(clazz, m, "M7", "Protected methods not allowed; must be public")
- for f in clazz.fields:
- if "protected" in f.split:
- error(clazz, f, "M7", "Protected fields not allowed; must be public")
-
-
-@verifier
-def verify_fields(clazz):
- """Verify that all exposed fields are final.
- Exposed fields must follow myName style.
- Catch internal mFoo objects being exposed."""
-
- IGNORE_BARE_FIELDS = [
- "android.app.ActivityManager.RecentTaskInfo",
- "android.app.Notification",
- "android.content.pm.ActivityInfo",
- "android.content.pm.ApplicationInfo",
- "android.content.pm.ComponentInfo",
- "android.content.pm.ResolveInfo",
- "android.content.pm.FeatureGroupInfo",
- "android.content.pm.InstrumentationInfo",
- "android.content.pm.PackageInfo",
- "android.content.pm.PackageItemInfo",
- "android.content.res.Configuration",
- "android.graphics.BitmapFactory.Options",
- "android.os.Message",
- "android.system.StructPollfd",
- ]
-
- for f in clazz.fields:
- if not "final" in f.split:
- if clazz.fullname in IGNORE_BARE_FIELDS:
- pass
- elif clazz.fullname.endswith("LayoutParams"):
- pass
- elif clazz.fullname.startswith("android.util.Mutable"):
- pass
- else:
- error(clazz, f, "F2", "Bare fields must be marked final, or add accessors if mutable")
-
- if "static" not in f.split and "property" not in f.split:
- if not re.match("[a-z]([a-zA-Z]+)?", f.name):
- error(clazz, f, "S1", "Non-static fields must be named using myField style")
-
- if re.match("[ms][A-Z]", f.name):
- error(clazz, f, "F1", "Internal objects must not be exposed")
-
- if re.match("[A-Z_]+", f.name):
- if "static" not in f.split or "final" not in f.split:
- error(clazz, f, "C2", "Constants must be marked static final")
-
-
-@verifier
-def verify_register(clazz):
- """Verify parity of registration methods.
- Callback objects use register/unregister methods.
- Listener objects use add/remove methods."""
- methods = [ m.name for m in clazz.methods ]
- for m in clazz.methods:
- if "Callback" in m.raw:
- if m.name.startswith("register"):
- other = "unregister" + m.name[8:]
- if other not in methods:
- error(clazz, m, "L2", "Missing unregister method")
- if m.name.startswith("unregister"):
- other = "register" + m.name[10:]
- if other not in methods:
- error(clazz, m, "L2", "Missing register method")
-
- if m.name.startswith("add") or m.name.startswith("remove"):
- error(clazz, m, "L3", "Callback methods should be named register/unregister")
-
- if "Listener" in m.raw:
- if m.name.startswith("add"):
- other = "remove" + m.name[3:]
- if other not in methods:
- error(clazz, m, "L2", "Missing remove method")
- if m.name.startswith("remove") and not m.name.startswith("removeAll"):
- other = "add" + m.name[6:]
- if other not in methods:
- error(clazz, m, "L2", "Missing add method")
-
- if m.name.startswith("register") or m.name.startswith("unregister"):
- error(clazz, m, "L3", "Listener methods should be named add/remove")
-
-
-@verifier
-def verify_sync(clazz):
- """Verify synchronized methods aren't exposed."""
- for m in clazz.methods:
- if "synchronized" in m.split:
- error(clazz, m, "M5", "Internal locks must not be exposed")
-
-
-@verifier
-def verify_intent_builder(clazz):
- """Verify that Intent builders are createFooIntent() style."""
- if clazz.name == "Intent": return
-
- for m in clazz.methods:
- if m.typ == "android.content.Intent":
- if m.name.startswith("create") and m.name.endswith("Intent"):
- pass
- else:
- warn(clazz, m, "FW1", "Methods creating an Intent should be named createFooIntent()")
-
-
-@verifier
-def verify_helper_classes(clazz):
- """Verify that helper classes are named consistently with what they extend.
- All developer extendable methods should be named onFoo()."""
- test_methods = False
- if clazz.extends == "android.app.Service":
- test_methods = True
- if not clazz.name.endswith("Service"):
- error(clazz, None, "CL4", "Inconsistent class name; should be FooService")
-
- found = False
- for f in clazz.fields:
- if f.name == "SERVICE_INTERFACE":
- found = True
- if f.value != clazz.fullname:
- error(clazz, f, "C4", "Inconsistent interface constant; expected '%s'" % (clazz.fullname))
-
- if clazz.extends == "android.content.ContentProvider":
- test_methods = True
- if not clazz.name.endswith("Provider"):
- error(clazz, None, "CL4", "Inconsistent class name; should be FooProvider")
-
- found = False
- for f in clazz.fields:
- if f.name == "PROVIDER_INTERFACE":
- found = True
- if f.value != clazz.fullname:
- error(clazz, f, "C4", "Inconsistent interface constant; expected '%s'" % (clazz.fullname))
-
- if clazz.extends == "android.content.BroadcastReceiver":
- test_methods = True
- if not clazz.name.endswith("Receiver"):
- error(clazz, None, "CL4", "Inconsistent class name; should be FooReceiver")
-
- if clazz.extends == "android.app.Activity":
- test_methods = True
- if not clazz.name.endswith("Activity"):
- error(clazz, None, "CL4", "Inconsistent class name; should be FooActivity")
-
- if test_methods:
- for m in clazz.methods:
- if "final" in m.split: continue
- if not re.match("on[A-Z]", m.name):
- if "abstract" in m.split:
- warn(clazz, m, None, "Methods implemented by developers should be named onFoo()")
- else:
- warn(clazz, m, None, "If implemented by developer, should be named onFoo(); otherwise consider marking final")
-
-
-@verifier
-def verify_builder(clazz):
- """Verify builder classes.
- Methods should return the builder to enable chaining."""
- if clazz.extends: return
- if not clazz.name.endswith("Builder"): return
-
- if clazz.name != "Builder":
- warn(clazz, None, None, "Builder should be defined as inner class")
-
- has_build = False
- for m in clazz.methods:
- if m.name == "build":
- has_build = True
- continue
-
- if m.name.startswith("get"): continue
- if m.name.startswith("clear"): continue
-
- if m.name.startswith("with"):
- warn(clazz, m, None, "Builder methods names should use setFoo() style")
-
- if m.name.startswith("set"):
- if not m.typ.endswith(clazz.fullname):
- warn(clazz, m, "M4", "Methods must return the builder object")
-
- if not has_build:
- warn(clazz, None, None, "Missing build() method")
-
- if "final" not in clazz.split:
- error(clazz, None, None, "Builder should be final")
-
-
-@verifier
-def verify_aidl(clazz):
- """Catch people exposing raw AIDL."""
- if clazz.extends == "android.os.Binder" or clazz.implements == "android.os.IInterface":
- error(clazz, None, None, "Raw AIDL interfaces must not be exposed")
-
-
-@verifier
-def verify_internal(clazz):
- """Catch people exposing internal classes."""
- if clazz.pkg.name.startswith("com.android"):
- error(clazz, None, None, "Internal classes must not be exposed")
-
-def layering_build_ranking(ranking_list):
- r = {}
- for rank, ps in enumerate(ranking_list):
- if not isinstance(ps, list):
- ps = [ps]
- for p in ps:
- rs = r
- for n in p.split('.'):
- if n not in rs:
- rs[n] = {}
- rs = rs[n]
- rs['-rank'] = rank
- return r
-
-LAYERING_PACKAGE_RANKING = layering_build_ranking([
- ["android.service","android.accessibilityservice","android.inputmethodservice","android.printservice","android.appwidget","android.webkit","android.preference","android.gesture","android.print"],
- "android.app",
- "android.widget",
- "android.view",
- "android.animation",
- "android.provider",
- ["android.content","android.graphics.drawable"],
- "android.database",
- "android.text",
- "android.graphics",
- "android.os",
- "android.util"
-])
-
-@verifier
-def verify_layering(clazz):
- """Catch package layering violations.
- For example, something in android.os depending on android.app."""
-
- def rank(p):
- r = None
- l = LAYERING_PACKAGE_RANKING
- for n in p.split('.'):
- if n in l:
- l = l[n]
- if '-rank' in l:
- r = l['-rank']
- else:
- break
- return r
-
- cr = rank(clazz.pkg.name)
- if cr is None: return
-
- for f in clazz.fields:
- ir = rank(f.typ)
- if ir is not None and ir < cr:
- warn(clazz, f, "FW6", "Field type violates package layering")
-
- for m in itertools.chain(clazz.methods, clazz.ctors):
- ir = rank(m.typ)
- if ir is not None and ir < cr:
- warn(clazz, m, "FW6", "Method return type violates package layering")
- for arg in m.args:
- ir = rank(arg)
- if ir is not None and ir < cr:
- warn(clazz, m, "FW6", "Method argument type violates package layering")
-
-
-@verifier
-def verify_boolean(clazz):
- """Verifies that boolean accessors are named correctly.
- For example, hasFoo() and setHasFoo()."""
-
- def is_get(m): return len(m.args) == 0 and m.typ == "boolean"
- def is_set(m): return len(m.args) == 1 and m.args[0] == "boolean"
-
- gets = [ m for m in clazz.methods if is_get(m) ]
- sets = [ m for m in clazz.methods if is_set(m) ]
-
- def error_if_exists(methods, trigger, expected, actual):
- for m in methods:
- if m.name == actual:
- error(clazz, m, "M6", "Symmetric method for %s must be named %s" % (trigger, expected))
-
- for m in clazz.methods:
- if is_get(m):
- if re.match("is[A-Z]", m.name):
- target = m.name[2:]
- expected = "setIs" + target
- error_if_exists(sets, m.name, expected, "setHas" + target)
- elif re.match("has[A-Z]", m.name):
- target = m.name[3:]
- expected = "setHas" + target
- error_if_exists(sets, m.name, expected, "setIs" + target)
- error_if_exists(sets, m.name, expected, "set" + target)
- elif re.match("get[A-Z]", m.name):
- target = m.name[3:]
- expected = "set" + target
- error_if_exists(sets, m.name, expected, "setIs" + target)
- error_if_exists(sets, m.name, expected, "setHas" + target)
-
- if is_set(m):
- if re.match("set[A-Z]", m.name):
- target = m.name[3:]
- expected = "get" + target
- error_if_exists(sets, m.name, expected, "is" + target)
- error_if_exists(sets, m.name, expected, "has" + target)
-
-
-@verifier
-def verify_collections(clazz):
- """Verifies that collection types are interfaces."""
- if clazz.fullname == "android.os.Bundle": return
- if clazz.fullname == "android.os.Parcel": return
-
- bad = ["java.util.Vector", "java.util.LinkedList", "java.util.ArrayList", "java.util.Stack",
- "java.util.HashMap", "java.util.HashSet", "android.util.ArraySet", "android.util.ArrayMap"]
- for m in clazz.methods:
- if m.typ in bad:
- error(clazz, m, "CL2", "Return type is concrete collection; must be higher-level interface")
- for arg in m.args:
- if arg in bad:
- error(clazz, m, "CL2", "Argument is concrete collection; must be higher-level interface")
-
-
-@verifier
-def verify_uris(clazz):
- bad = ["java.net.URL", "java.net.URI", "android.net.URL"]
-
- for f in clazz.fields:
- if f.typ in bad:
- error(clazz, f, None, "Field must be android.net.Uri instead of " + f.typ)
-
- for m in clazz.methods + clazz.ctors:
- if m.typ in bad:
- error(clazz, m, None, "Must return android.net.Uri instead of " + m.typ)
- for arg in m.args:
- if arg in bad:
- error(clazz, m, None, "Argument must take android.net.Uri instead of " + arg)
-
-
-@verifier
-def verify_flags(clazz):
- """Verifies that flags are non-overlapping."""
- known = collections.defaultdict(int)
- for f in clazz.fields:
- if "FLAG_" in f.name:
- try:
- val = int(f.value)
- except:
- continue
-
- scope = f.name[0:f.name.index("FLAG_")]
- if val & known[scope]:
- warn(clazz, f, "C1", "Found overlapping flag constant value")
- known[scope] |= val
-
-
-@verifier
-def verify_exception(clazz):
- """Verifies that methods don't throw generic exceptions."""
- for m in clazz.methods:
- for t in m.throws:
- if t in ["java.lang.Exception", "java.lang.Throwable", "java.lang.Error"]:
- error(clazz, m, "S1", "Methods must not throw generic exceptions")
-
- if t in ["android.os.RemoteException"]:
- if clazz.fullname == "android.content.ContentProviderClient": continue
- if clazz.fullname == "android.os.Binder": continue
- if clazz.fullname == "android.os.IBinder": continue
-
- error(clazz, m, "FW9", "Methods calling into system server should rethrow RemoteException as RuntimeException")
-
- if len(m.args) == 0 and t in ["java.lang.IllegalArgumentException", "java.lang.NullPointerException"]:
- warn(clazz, m, "S1", "Methods taking no arguments should throw IllegalStateException")
-
-
-GOOGLE_IGNORECASE = re.compile("google", re.IGNORECASE)
-
-# Not marked as @verifier, because it is only conditionally applied.
-def verify_google(clazz):
- """Verifies that APIs never reference Google."""
-
- if GOOGLE_IGNORECASE.search(clazz.raw) is not None:
- error(clazz, None, None, "Must never reference Google")
-
- for test in clazz.ctors, clazz.fields, clazz.methods:
- for t in test:
- if GOOGLE_IGNORECASE.search(t.raw) is not None:
- error(clazz, t, None, "Must never reference Google")
-
-
-@verifier
-def verify_bitset(clazz):
- """Verifies that we avoid using heavy BitSet."""
-
- for f in clazz.fields:
- if f.typ == "java.util.BitSet":
- error(clazz, f, None, "Field type must not be heavy BitSet")
-
- for m in clazz.methods:
- if m.typ == "java.util.BitSet":
- error(clazz, m, None, "Return type must not be heavy BitSet")
- for arg in m.args:
- if arg == "java.util.BitSet":
- error(clazz, m, None, "Argument type must not be heavy BitSet")
-
-
-@verifier
-def verify_manager(clazz):
- """Verifies that FooManager is only obtained from Context."""
-
- if not clazz.name.endswith("Manager"): return
-
- for c in clazz.ctors:
- error(clazz, c, None, "Managers must always be obtained from Context; no direct constructors")
-
- for m in clazz.methods:
- if m.typ == clazz.fullname:
- error(clazz, m, None, "Managers must always be obtained from Context")
-
-
-@verifier
-def verify_boxed(clazz):
- """Verifies that methods avoid boxed primitives."""
-
- boxed = ["java.lang.Number","java.lang.Byte","java.lang.Double","java.lang.Float","java.lang.Integer","java.lang.Long","java.lang.Short"]
-
- for c in clazz.ctors:
- for arg in c.args:
- if arg in boxed:
- error(clazz, c, "M11", "Must avoid boxed primitives")
-
- for f in clazz.fields:
- if f.typ in boxed:
- error(clazz, f, "M11", "Must avoid boxed primitives")
-
- for m in clazz.methods:
- if m.typ in boxed:
- error(clazz, m, "M11", "Must avoid boxed primitives")
- for arg in m.args:
- if arg in boxed:
- error(clazz, m, "M11", "Must avoid boxed primitives")
-
-
-@verifier
-def verify_static_utils(clazz):
- """Verifies that helper classes can't be constructed."""
- if clazz.fullname.startswith("android.opengl"): return
- if clazz.fullname.startswith("android.R"): return
-
- # Only care about classes with default constructors
- if len(clazz.ctors) == 1 and len(clazz.ctors[0].args) == 0:
- test = []
- test.extend(clazz.fields)
- test.extend(clazz.methods)
-
- if len(test) == 0: return
- for t in test:
- if "static" not in t.split:
- return
-
- error(clazz, None, None, "Fully-static utility classes must not have constructor")
-
-
-# @verifier # Disabled for now
-def verify_overload_args(clazz):
- """Verifies that method overloads add new arguments at the end."""
- if clazz.fullname.startswith("android.opengl"): return
-
- overloads = collections.defaultdict(list)
- for m in clazz.methods:
- if "deprecated" in m.split: continue
- overloads[m.name].append(m)
-
- for name, methods in overloads.items():
- if len(methods) <= 1: continue
-
- # Look for arguments common across all overloads
- def cluster(args):
- count = collections.defaultdict(int)
- res = set()
- for i in range(len(args)):
- a = args[i]
- res.add("%s#%d" % (a, count[a]))
- count[a] += 1
- return res
-
- common_args = cluster(methods[0].args)
- for m in methods:
- common_args = common_args & cluster(m.args)
-
- if len(common_args) == 0: continue
-
- # Require that all common arguments are present at start of signature
- locked_sig = None
- for m in methods:
- sig = m.args[0:len(common_args)]
- if not common_args.issubset(cluster(sig)):
- warn(clazz, m, "M2", "Expected common arguments [%s] at beginning of overloaded method" % (", ".join(common_args)))
- elif not locked_sig:
- locked_sig = sig
- elif locked_sig != sig:
- error(clazz, m, "M2", "Expected consistent argument ordering between overloads: %s..." % (", ".join(locked_sig)))
-
-
-@verifier
-def verify_callback_handlers(clazz):
- """Verifies that methods adding listener/callback have overload
- for specifying delivery thread."""
-
- # Ignore UI packages which assume main thread
- skip = [
- "animation",
- "view",
- "graphics",
- "transition",
- "widget",
- "webkit",
- ]
- for s in skip:
- if s in clazz.pkg.name_path: return
- if s in clazz.extends_path: return
-
- # Ignore UI classes which assume main thread
- if "app" in clazz.pkg.name_path or "app" in clazz.extends_path:
- for s in ["ActionBar","Dialog","Application","Activity","Fragment","Loader"]:
- if s in clazz.fullname: return
- if "content" in clazz.pkg.name_path or "content" in clazz.extends_path:
- for s in ["Loader"]:
- if s in clazz.fullname: return
-
- found = {}
- by_name = collections.defaultdict(list)
- examine = clazz.ctors + clazz.methods
- for m in examine:
- if m.name.startswith("unregister"): continue
- if m.name.startswith("remove"): continue
- if re.match("on[A-Z]+", m.name): continue
-
- by_name[m.name].append(m)
-
- for a in m.args:
- if a.endswith("Listener") or a.endswith("Callback") or a.endswith("Callbacks"):
- found[m.name] = m
-
- for f in found.values():
- takes_handler = False
- takes_exec = False
- for m in by_name[f.name]:
- if "android.os.Handler" in m.args:
- takes_handler = True
- if "java.util.concurrent.Executor" in m.args:
- takes_exec = True
- if not takes_exec:
- warn(clazz, f, "L1", "Registration methods should have overload that accepts delivery Executor")
-
-
-@verifier
-def verify_context_first(clazz):
- """Verifies that methods accepting a Context keep it the first argument."""
- examine = clazz.ctors + clazz.methods
- for m in examine:
- if len(m.args) > 1 and m.args[0] != "android.content.Context":
- if "android.content.Context" in m.args[1:]:
- error(clazz, m, "M3", "Context is distinct, so it must be the first argument")
- if len(m.args) > 1 and m.args[0] != "android.content.ContentResolver":
- if "android.content.ContentResolver" in m.args[1:]:
- error(clazz, m, "M3", "ContentResolver is distinct, so it must be the first argument")
-
-
-@verifier
-def verify_listener_last(clazz):
- """Verifies that methods accepting a Listener or Callback keep them as last arguments."""
- examine = clazz.ctors + clazz.methods
- for m in examine:
- if "Listener" in m.name or "Callback" in m.name: continue
- found = False
- for a in m.args:
- if a.endswith("Callback") or a.endswith("Callbacks") or a.endswith("Listener"):
- found = True
- elif found:
- warn(clazz, m, "M3", "Listeners should always be at end of argument list")
-
-
-@verifier
-def verify_resource_names(clazz):
- """Verifies that resource names have consistent case."""
- if not re.match("android\.R\.[a-z]+", clazz.fullname): return
-
- # Resources defined by files are foo_bar_baz
- if clazz.name in ["anim","animator","color","dimen","drawable","interpolator","layout","transition","menu","mipmap","string","plurals","raw","xml"]:
- for f in clazz.fields:
- if re.match("config_[a-z][a-zA-Z1-9]*$", f.name): continue
- if f.name.startswith("config_"):
- error(clazz, f, None, "Expected config name to be config_fooBarBaz style")
-
- if re.match("[a-z1-9_]+$", f.name): continue
- error(clazz, f, None, "Expected resource name in this class to be foo_bar_baz style")
-
- # Resources defined inside files are fooBarBaz
- if clazz.name in ["array","attr","id","bool","fraction","integer"]:
- for f in clazz.fields:
- if re.match("config_[a-z][a-zA-Z1-9]*$", f.name): continue
- if re.match("layout_[a-z][a-zA-Z1-9]*$", f.name): continue
- if re.match("state_[a-z_]*$", f.name): continue
-
- if re.match("[a-z][a-zA-Z1-9]*$", f.name): continue
- error(clazz, f, "C7", "Expected resource name in this class to be fooBarBaz style")
-
- # Styles are FooBar_Baz
- if clazz.name in ["style"]:
- for f in clazz.fields:
- if re.match("[A-Z][A-Za-z1-9]+(_[A-Z][A-Za-z1-9]+?)*$", f.name): continue
- error(clazz, f, "C7", "Expected resource name in this class to be FooBar_Baz style")
-
-
-@verifier
-def verify_files(clazz):
- """Verifies that methods accepting File also accept streams."""
-
- has_file = set()
- has_stream = set()
-
- test = []
- test.extend(clazz.ctors)
- test.extend(clazz.methods)
-
- for m in test:
- if "java.io.File" in m.args:
- has_file.add(m)
- if "java.io.FileDescriptor" in m.args or "android.os.ParcelFileDescriptor" in m.args or "java.io.InputStream" in m.args or "java.io.OutputStream" in m.args:
- has_stream.add(m.name)
-
- for m in has_file:
- if m.name not in has_stream:
- warn(clazz, m, "M10", "Methods accepting File should also accept FileDescriptor or streams")
-
-
-@verifier
-def verify_manager_list(clazz):
- """Verifies that managers return List<? extends Parcelable> instead of arrays."""
-
- if not clazz.name.endswith("Manager"): return
-
- for m in clazz.methods:
- if m.typ.startswith("android.") and m.typ.endswith("[]"):
- warn(clazz, m, None, "Methods should return List<? extends Parcelable> instead of Parcelable[] to support ParceledListSlice under the hood")
-
-
-@verifier
-def verify_abstract_inner(clazz):
- """Verifies that abstract inner classes are static."""
-
- if re.match(".+?\.[A-Z][^\.]+\.[A-Z]", clazz.fullname):
- if "abstract" in clazz.split and "static" not in clazz.split:
- warn(clazz, None, None, "Abstract inner classes should be static to improve testability")
-
-
-@verifier
-def verify_runtime_exceptions(clazz):
- """Verifies that runtime exceptions aren't listed in throws."""
-
- banned = [
- "java.lang.NullPointerException",
- "java.lang.ClassCastException",
- "java.lang.IndexOutOfBoundsException",
- "java.lang.reflect.UndeclaredThrowableException",
- "java.lang.reflect.MalformedParametersException",
- "java.lang.reflect.MalformedParameterizedTypeException",
- "java.lang.invoke.WrongMethodTypeException",
- "java.lang.EnumConstantNotPresentException",
- "java.lang.IllegalMonitorStateException",
- "java.lang.SecurityException",
- "java.lang.UnsupportedOperationException",
- "java.lang.annotation.AnnotationTypeMismatchException",
- "java.lang.annotation.IncompleteAnnotationException",
- "java.lang.TypeNotPresentException",
- "java.lang.IllegalStateException",
- "java.lang.ArithmeticException",
- "java.lang.IllegalArgumentException",
- "java.lang.ArrayStoreException",
- "java.lang.NegativeArraySizeException",
- "java.util.MissingResourceException",
- "java.util.EmptyStackException",
- "java.util.concurrent.CompletionException",
- "java.util.concurrent.RejectedExecutionException",
- "java.util.IllformedLocaleException",
- "java.util.ConcurrentModificationException",
- "java.util.NoSuchElementException",
- "java.io.UncheckedIOException",
- "java.time.DateTimeException",
- "java.security.ProviderException",
- "java.nio.BufferUnderflowException",
- "java.nio.BufferOverflowException",
- ]
-
- examine = clazz.ctors + clazz.methods
- for m in examine:
- for t in m.throws:
- if t in banned:
- error(clazz, m, None, "Methods must not mention RuntimeException subclasses in throws clauses")
-
-
-@verifier
-def verify_error(clazz):
- """Verifies that we always use Exception instead of Error."""
- if not clazz.extends: return
- if clazz.extends.endswith("Error"):
- error(clazz, None, None, "Trouble must be reported through an Exception, not Error")
- if clazz.extends.endswith("Exception") and not clazz.name.endswith("Exception"):
- error(clazz, None, None, "Exceptions must be named FooException")
-
-
-@verifier
-def verify_units(clazz):
- """Verifies that we use consistent naming for units."""
-
- # If we find K, recommend replacing with V
- bad = {
- "Ns": "Nanos",
- "Ms": "Millis or Micros",
- "Sec": "Seconds", "Secs": "Seconds",
- "Hr": "Hours", "Hrs": "Hours",
- "Mo": "Months", "Mos": "Months",
- "Yr": "Years", "Yrs": "Years",
- "Byte": "Bytes", "Space": "Bytes",
- }
-
- for m in clazz.methods:
- if m.typ not in ["short","int","long"]: continue
- for k, v in bad.iteritems():
- if m.name.endswith(k):
- error(clazz, m, None, "Expected method name units to be " + v)
- if m.name.endswith("Nanos") or m.name.endswith("Micros"):
- warn(clazz, m, None, "Returned time values are strongly encouraged to be in milliseconds unless you need the extra precision")
- if m.name.endswith("Seconds"):
- error(clazz, m, None, "Returned time values must be in milliseconds")
-
- for m in clazz.methods:
- typ = m.typ
- if typ == "void":
- if len(m.args) != 1: continue
- typ = m.args[0]
-
- if m.name.endswith("Fraction") and typ != "float":
- error(clazz, m, None, "Fractions must use floats")
- if m.name.endswith("Percentage") and typ != "int":
- error(clazz, m, None, "Percentage must use ints")
-
-
-@verifier
-def verify_closable(clazz):
- """Verifies that classes are AutoClosable."""
- if "java.lang.AutoCloseable" in clazz.implements_all: return
- if "java.io.Closeable" in clazz.implements_all: return
-
- for m in clazz.methods:
- if len(m.args) > 0: continue
- if m.name in ["close","release","destroy","finish","finalize","disconnect","shutdown","stop","free","quit"]:
- warn(clazz, m, None, "Classes that release resources should implement AutoClosable and CloseGuard")
- return
-
-
-@verifier
-def verify_member_name_not_kotlin_keyword(clazz):
- """Prevent method names which are keywords in Kotlin."""
-
- # https://kotlinlang.org/docs/reference/keyword-reference.html#hard-keywords
- # This list does not include Java keywords as those are already impossible to use.
- keywords = [
- 'as',
- 'fun',
- 'in',
- 'is',
- 'object',
- 'typealias',
- 'val',
- 'var',
- 'when',
- ]
-
- for m in clazz.methods:
- if m.name in keywords:
- error(clazz, m, None, "Method name must not be a Kotlin keyword")
- for f in clazz.fields:
- if f.name in keywords:
- error(clazz, f, None, "Field name must not be a Kotlin keyword")
-
-
-@verifier
-def verify_method_name_not_kotlin_operator(clazz):
- """Warn about method names which become operators in Kotlin."""
-
- binary = set()
-
- def unique_binary_op(m, op):
- if op in binary:
- error(clazz, m, None, "Only one of '{0}' and '{0}Assign' methods should be present for Kotlin".format(op))
- binary.add(op)
-
- for m in clazz.methods:
- if 'static' in m.split or 'operator' in m.split:
- continue
-
- # https://kotlinlang.org/docs/reference/operator-overloading.html#unary-prefix-operators
- if m.name in ['unaryPlus', 'unaryMinus', 'not'] and len(m.args) == 0:
- warn(clazz, m, None, "Method can be invoked as a unary operator from Kotlin")
-
- # https://kotlinlang.org/docs/reference/operator-overloading.html#increments-and-decrements
- if m.name in ['inc', 'dec'] and len(m.args) == 0 and m.typ != 'void':
- # This only applies if the return type is the same or a subtype of the enclosing class, but we have no
- # practical way of checking that relationship here.
- warn(clazz, m, None, "Method can be invoked as a pre/postfix inc/decrement operator from Kotlin")
-
- # https://kotlinlang.org/docs/reference/operator-overloading.html#arithmetic
- if m.name in ['plus', 'minus', 'times', 'div', 'rem', 'mod', 'rangeTo'] and len(m.args) == 1:
- warn(clazz, m, None, "Method can be invoked as a binary operator from Kotlin")
- unique_binary_op(m, m.name)
-
- # https://kotlinlang.org/docs/reference/operator-overloading.html#in
- if m.name == 'contains' and len(m.args) == 1 and m.typ == 'boolean':
- warn(clazz, m, None, "Method can be invoked as a 'in' operator from Kotlin")
-
- # https://kotlinlang.org/docs/reference/operator-overloading.html#indexed
- if (m.name == 'get' and len(m.args) > 0) or (m.name == 'set' and len(m.args) > 1):
- warn(clazz, m, None, "Method can be invoked with an indexing operator from Kotlin")
-
- # https://kotlinlang.org/docs/reference/operator-overloading.html#invoke
- if m.name == 'invoke':
- warn(clazz, m, None, "Method can be invoked with function call syntax from Kotlin")
-
- # https://kotlinlang.org/docs/reference/operator-overloading.html#assignments
- if m.name in ['plusAssign', 'minusAssign', 'timesAssign', 'divAssign', 'remAssign', 'modAssign'] \
- and len(m.args) == 1 \
- and m.typ == 'void':
- warn(clazz, m, None, "Method can be invoked as a compound assignment operator from Kotlin")
- unique_binary_op(m, m.name[:-6]) # Remove 'Assign' suffix
-
-
-@verifier
-def verify_collections_over_arrays(clazz):
- """Warn that [] should be Collections."""
-
- if "@interface" in clazz.split:
- return
-
- safe = ["java.lang.String[]","byte[]","short[]","int[]","long[]","float[]","double[]","boolean[]","char[]"]
- for m in clazz.methods:
- if m.typ.endswith("[]") and m.typ not in safe:
- warn(clazz, m, None, "Method should return Collection<> (or subclass) instead of raw array")
- for arg in m.args:
- if arg.endswith("[]") and arg not in safe:
- warn(clazz, m, None, "Method argument should be Collection<> (or subclass) instead of raw array")
-
-
-@verifier
-def verify_user_handle(clazz):
- """Methods taking UserHandle should be ForUser or AsUser."""
- if clazz.name.endswith("Listener") or clazz.name.endswith("Callback") or clazz.name.endswith("Callbacks"): return
- if clazz.fullname == "android.app.admin.DeviceAdminReceiver": return
- if clazz.fullname == "android.content.pm.LauncherApps": return
- if clazz.fullname == "android.os.UserHandle": return
- if clazz.fullname == "android.os.UserManager": return
-
- for m in clazz.methods:
- if re.match("on[A-Z]+", m.name): continue
-
- has_arg = "android.os.UserHandle" in m.args
- has_name = m.name.endswith("AsUser") or m.name.endswith("ForUser")
-
- if clazz.fullname.endswith("Manager") and has_arg:
- warn(clazz, m, None, "When a method overload is needed to target a specific "
- "UserHandle, callers should be directed to use "
- "Context.createPackageContextAsUser() and re-obtain the relevant "
- "Manager, and no new API should be added")
- elif has_arg and not has_name:
- warn(clazz, m, None, "Method taking UserHandle should be named 'doFooAsUser' "
- "or 'queryFooForUser'")
-
-
-@verifier
-def verify_params(clazz):
- """Parameter classes should be 'Params'."""
- if clazz.name.endswith("Params"): return
- if clazz.fullname == "android.app.ActivityOptions": return
- if clazz.fullname == "android.app.BroadcastOptions": return
- if clazz.fullname == "android.os.Bundle": return
- if clazz.fullname == "android.os.BaseBundle": return
- if clazz.fullname == "android.os.PersistableBundle": return
-
- bad = ["Param","Parameter","Parameters","Args","Arg","Argument","Arguments","Options","Bundle"]
- for b in bad:
- if clazz.name.endswith(b):
- error(clazz, None, None, "Classes holding a set of parameters should be called 'FooParams'")
-
-
-@verifier
-def verify_services(clazz):
- """Service name should be FOO_BAR_SERVICE = 'foo_bar'."""
- if clazz.fullname != "android.content.Context": return
-
- for f in clazz.fields:
- if f.typ != "java.lang.String": continue
- found = re.match(r"([A-Z_]+)_SERVICE", f.name)
- if found:
- expected = found.group(1).lower()
- if f.value != expected:
- error(clazz, f, "C4", "Inconsistent service value; expected '%s'" % (expected))
-
-
-@verifier
-def verify_tense(clazz):
- """Verify tenses of method names."""
- if clazz.fullname.startswith("android.opengl"): return
-
- for m in clazz.methods:
- if m.name.endswith("Enable"):
- warn(clazz, m, None, "Unexpected tense; probably meant 'enabled'")
-
-
-@verifier
-def verify_icu(clazz):
- """Verifies that richer ICU replacements are used."""
- better = {
- "java.util.TimeZone": "android.icu.util.TimeZone",
- "java.util.Calendar": "android.icu.util.Calendar",
- "java.util.Locale": "android.icu.util.ULocale",
- "java.util.ResourceBundle": "android.icu.util.UResourceBundle",
- "java.util.SimpleTimeZone": "android.icu.util.SimpleTimeZone",
- "java.util.StringTokenizer": "android.icu.util.StringTokenizer",
- "java.util.GregorianCalendar": "android.icu.util.GregorianCalendar",
- "java.lang.Character": "android.icu.lang.UCharacter",
- "java.text.BreakIterator": "android.icu.text.BreakIterator",
- "java.text.Collator": "android.icu.text.Collator",
- "java.text.DecimalFormatSymbols": "android.icu.text.DecimalFormatSymbols",
- "java.text.NumberFormat": "android.icu.text.NumberFormat",
- "java.text.DateFormatSymbols": "android.icu.text.DateFormatSymbols",
- "java.text.DateFormat": "android.icu.text.DateFormat",
- "java.text.SimpleDateFormat": "android.icu.text.SimpleDateFormat",
- "java.text.MessageFormat": "android.icu.text.MessageFormat",
- "java.text.DecimalFormat": "android.icu.text.DecimalFormat",
- }
-
- for m in clazz.ctors + clazz.methods:
- types = []
- types.extend(m.typ)
- types.extend(m.args)
- for arg in types:
- if arg in better:
- warn(clazz, m, None, "Type %s should be replaced with richer ICU type %s" % (arg, better[arg]))
-
-
-@verifier
-def verify_clone(clazz):
- """Verify that clone() isn't implemented; see EJ page 61."""
- for m in clazz.methods:
- if m.name == "clone":
- error(clazz, m, None, "Provide an explicit copy constructor instead of implementing clone()")
-
-
-@verifier
-def verify_pfd(clazz):
- """Verify that android APIs use PFD over FD."""
- if clazz.fullname == "android.os.FileUtils" or clazz.fullname == "android.system.Os":
- return
-
- examine = clazz.ctors + clazz.methods
- for m in examine:
- if m.typ == "java.io.FileDescriptor":
- error(clazz, m, "FW11", "Must use ParcelFileDescriptor")
- if m.typ == "int":
- if "Fd" in m.name or "FD" in m.name or "FileDescriptor" in m.name:
- error(clazz, m, "FW11", "Must use ParcelFileDescriptor")
- for arg in m.args:
- if arg == "java.io.FileDescriptor":
- error(clazz, m, "FW11", "Must use ParcelFileDescriptor")
-
- for f in clazz.fields:
- if f.typ == "java.io.FileDescriptor":
- error(clazz, f, "FW11", "Must use ParcelFileDescriptor")
-
-
-@verifier
-def verify_numbers(clazz):
- """Discourage small numbers types like short and byte."""
-
- discouraged = ["short","byte"]
-
- for c in clazz.ctors:
- for arg in c.args:
- if arg in discouraged:
- warn(clazz, c, "FW12", "Should avoid odd sized primitives; use int instead")
-
- for f in clazz.fields:
- if f.typ in discouraged:
- warn(clazz, f, "FW12", "Should avoid odd sized primitives; use int instead")
-
- for m in clazz.methods:
- if m.typ in discouraged:
- warn(clazz, m, "FW12", "Should avoid odd sized primitives; use int instead")
- for arg in m.args:
- if arg in discouraged:
- warn(clazz, m, "FW12", "Should avoid odd sized primitives; use int instead")
-
-
-PRIMITIVES = {"void", "int", "float", "boolean", "short", "char", "byte", "long", "double"}
-
-@verifier
-def verify_nullability(clazz):
- """Catches missing nullability annotations"""
-
- for f in clazz.fields:
- if "enum_constant" in f.split:
- continue # Enum constants are never null
- if f.value is not None and 'final' in f.split:
- continue # Nullability of constants can be inferred.
- if f.typ not in PRIMITIVES and not has_nullability(f.annotations):
- error(clazz, f, "M12", "Field must be marked either @NonNull or @Nullable")
-
- for c in clazz.ctors:
- verify_nullability_args(clazz, c)
-
- for m in clazz.methods:
- if m.name == "writeToParcel" or m.name == "onReceive" or m.name == "onBind":
- continue # Parcelable.writeToParcel(), BroadcastReceiver.onReceive(), and Service.onBind() are not yet annotated
-
- if (m.name == "equals" and m.args == ["java.lang.Object"] or
- m.name == "toString" and m.args == []):
- continue # Nullability of equals and toString is implicit.
-
- if m.typ not in PRIMITIVES and not has_nullability(m.annotations):
- error(clazz, m, "M12", "Return value must be marked either @NonNull or @Nullable")
- verify_nullability_args(clazz, m)
-
-def verify_nullability_args(clazz, m):
- for i, arg in enumerate(m.detailed_args):
- if arg.type not in PRIMITIVES and not has_nullability(arg.annotations):
- error(clazz, m, "M12", "Argument %d must be marked either @NonNull or @Nullable" % (i+1,))
-
-def has_nullability(annotations):
- return "@NonNull" in annotations or "@Nullable" in annotations
-
-
-@verifier
-def verify_intdef(clazz):
- """intdefs must be @hide, because the constant names cannot be stored in
- the stubs (only the values are, which is not useful)"""
- if "@interface" not in clazz.split:
- return
- if "@IntDef" in clazz.annotations or "@LongDef" in clazz.annotations:
- error(clazz, None, None, "@IntDef and @LongDef annotations must be @hide")
-
-
-@verifier
-def verify_singleton(clazz):
- """Catch singleton objects with constructors."""
-
- singleton = False
- for m in clazz.methods:
- if m.name.startswith("get") and m.name.endswith("Instance") and " static " in m.raw:
- singleton = True
-
- if singleton:
- for c in clazz.ctors:
- error(clazz, c, None, "Singleton classes should use getInstance() methods")
-
-
-
-def is_interesting(clazz):
- """Test if given class is interesting from an Android PoV."""
-
- if clazz.pkg.name.startswith("java"): return False
- if clazz.pkg.name.startswith("junit"): return False
- if clazz.pkg.name.startswith("org.apache"): return False
- if clazz.pkg.name.startswith("org.xml"): return False
- if clazz.pkg.name.startswith("org.json"): return False
- if clazz.pkg.name.startswith("org.w3c"): return False
- if clazz.pkg.name.startswith("android.icu."): return False
- return True
-
-
-def examine_clazz(clazz):
- """Find all style issues in the given class."""
-
- notice(clazz)
-
- if not is_interesting(clazz): return
-
- for v in verifiers.itervalues():
- v(clazz)
-
- if not ALLOW_GOOGLE: verify_google(clazz)
-
-
-def examine_stream(stream, base_stream=None, in_classes_with_base=[], out_classes_with_base=None):
- """Find all style issues in the given API stream."""
- global failures, noticed
- failures = {}
- noticed = {}
- _parse_stream(stream, examine_clazz, base_f=base_stream,
- in_classes_with_base=in_classes_with_base,
- out_classes_with_base=out_classes_with_base)
- return (failures, noticed)
-
-
-def examine_api(api):
- """Find all style issues in the given parsed API."""
- global failures
- failures = {}
- for key in sorted(api.keys()):
- examine_clazz(api[key])
- return failures
-
-
-def verify_compat(cur, prev):
- """Find any incompatible API changes between two levels."""
- global failures
-
- def class_exists(api, test):
- return test.fullname in api
-
- def ctor_exists(api, clazz, test):
- for m in clazz.ctors:
- if m.ident == test.ident: return True
- return False
-
- def all_methods(api, clazz):
- methods = list(clazz.methods)
- if clazz.extends is not None:
- methods.extend(all_methods(api, api[clazz.extends]))
- return methods
-
- def method_exists(api, clazz, test):
- methods = all_methods(api, clazz)
- for m in methods:
- if m.ident == test.ident: return True
- return False
-
- def field_exists(api, clazz, test):
- for f in clazz.fields:
- if f.ident == test.ident: return True
- return False
-
- failures = {}
- for key in sorted(prev.keys()):
- prev_clazz = prev[key]
-
- if not class_exists(cur, prev_clazz):
- error(prev_clazz, None, None, "Class removed or incompatible change")
- continue
-
- cur_clazz = cur[key]
-
- for test in prev_clazz.ctors:
- if not ctor_exists(cur, cur_clazz, test):
- error(prev_clazz, prev_ctor, None, "Constructor removed or incompatible change")
-
- methods = all_methods(prev, prev_clazz)
- for test in methods:
- if not method_exists(cur, cur_clazz, test):
- error(prev_clazz, test, None, "Method removed or incompatible change")
-
- for test in prev_clazz.fields:
- if not field_exists(cur, cur_clazz, test):
- error(prev_clazz, test, None, "Field removed or incompatible change")
-
- return failures
-
-
-def match_filter(filters, fullname):
- for f in filters:
- if fullname == f:
- return True
- if fullname.startswith(f + '.'):
- return True
- return False
-
-
-def show_deprecations_at_birth(cur, prev):
- """Show API deprecations at birth."""
- global failures
-
- # Remove all existing things so we're left with new
- for prev_clazz in prev.values():
- if prev_clazz.fullname not in cur:
- # The class was removed this release; we can safely ignore it.
- continue
-
- cur_clazz = cur[prev_clazz.fullname]
- if not is_interesting(cur_clazz): continue
-
- sigs = { i.ident: i for i in prev_clazz.ctors }
- cur_clazz.ctors = [ i for i in cur_clazz.ctors if i.ident not in sigs ]
- sigs = { i.ident: i for i in prev_clazz.methods }
- cur_clazz.methods = [ i for i in cur_clazz.methods if i.ident not in sigs ]
- sigs = { i.ident: i for i in prev_clazz.fields }
- cur_clazz.fields = [ i for i in cur_clazz.fields if i.ident not in sigs ]
-
- # Forget about class entirely when nothing new
- if len(cur_clazz.ctors) == 0 and len(cur_clazz.methods) == 0 and len(cur_clazz.fields) == 0:
- del cur[prev_clazz.fullname]
-
- for clazz in cur.values():
- if not is_interesting(clazz): continue
-
- if "deprecated" in clazz.split and not clazz.fullname in prev:
- error(clazz, None, None, "Found API deprecation at birth")
-
- for i in clazz.ctors + clazz.methods + clazz.fields:
- if "deprecated" in i.split:
- error(clazz, i, None, "Found API deprecation at birth")
-
- print "%s Deprecated at birth %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True),
- format(reset=True)))
- for f in sorted(failures):
- print failures[f]
- print
-
-
-def show_stats(cur, prev):
- """Show API stats."""
-
- stats = collections.defaultdict(int)
- for cur_clazz in cur.values():
- if not is_interesting(cur_clazz): continue
-
- if cur_clazz.fullname not in prev:
- stats['new_classes'] += 1
- stats['new_ctors'] += len(cur_clazz.ctors)
- stats['new_methods'] += len(cur_clazz.methods)
- stats['new_fields'] += len(cur_clazz.fields)
- else:
- prev_clazz = prev[cur_clazz.fullname]
-
- sigs = { i.ident: i for i in prev_clazz.ctors }
- ctors = len([ i for i in cur_clazz.ctors if i.ident not in sigs ])
- sigs = { i.ident: i for i in prev_clazz.methods }
- methods = len([ i for i in cur_clazz.methods if i.ident not in sigs ])
- sigs = { i.ident: i for i in prev_clazz.fields }
- fields = len([ i for i in cur_clazz.fields if i.ident not in sigs ])
-
- if ctors + methods + fields > 0:
- stats['extend_classes'] += 1
- stats['extend_ctors'] += ctors
- stats['extend_methods'] += methods
- stats['extend_fields'] += fields
-
- print "#", "".join([ k.ljust(20) for k in sorted(stats.keys()) ])
- print " ", "".join([ str(stats[k]).ljust(20) for k in sorted(stats.keys()) ])
-
-
-def main():
- parser = argparse.ArgumentParser(description="Enforces common Android public API design \
- patterns. It ignores lint messages from a previous API level, if provided.")
- parser.add_argument("--base-current", nargs='?', type=argparse.FileType('r'), default=None,
- help="The base current.txt to use when examining system-current.txt or"
- " test-current.txt")
- parser.add_argument("--base-previous", nargs='?', type=argparse.FileType('r'), default=None,
- help="The base previous.txt to use when examining system-previous.txt or"
- " test-previous.txt")
- parser.add_argument("--no-color", action='store_const', const=True,
- help="Disable terminal colors")
- parser.add_argument("--color", action='store_const', const=True,
- help="Use terminal colors")
- parser.add_argument("--allow-google", action='store_const', const=True,
- help="Allow references to Google")
- parser.add_argument("--show-noticed", action='store_const', const=True,
- help="Show API changes noticed")
- parser.add_argument("--show-deprecations-at-birth", action='store_const', const=True,
- help="Show API deprecations at birth")
- parser.add_argument("--show-stats", action='store_const', const=True,
- help="Show API stats")
- parser.add_argument("--title", action='store', default=None,
- help="Title to put in for display purposes")
- parser.add_argument("--filter", action="append",
- help="If provided, only show lint for the given packages or classes.")
- parser.add_argument("current.txt", type=argparse.FileType('r'), help="current.txt")
- parser.add_argument("previous.txt", nargs='?', type=argparse.FileType('r'), default=None,
- help="previous.txt")
- args = vars(parser.parse_args())
-
- if args['no_color']:
- USE_COLOR = False
- elif args['color']:
- USE_COLOR = True
- else:
- USE_COLOR = sys.stdout.isatty()
-
- if args['allow_google']:
- ALLOW_GOOGLE = True
-
- current_file = args['current.txt']
- base_current_file = args['base_current']
- previous_file = args['previous.txt']
- base_previous_file = args['base_previous']
- filters = args['filter']
- if not filters:
- filters = []
- title = args['title']
- if not title:
- title = current_file.name
-
- if args['show_deprecations_at_birth']:
- with current_file as f:
- cur = _parse_stream(f)
- with previous_file as f:
- prev = _parse_stream(f)
- show_deprecations_at_birth(cur, prev)
- sys.exit()
-
- if args['show_stats']:
- with current_file as f:
- cur = _parse_stream(f)
- with previous_file as f:
- prev = _parse_stream(f)
- show_stats(cur, prev)
- sys.exit()
-
- classes_with_base = []
-
- with current_file as f:
- if base_current_file:
- with base_current_file as base_f:
- cur_fail, cur_noticed = examine_stream(f, base_f,
- out_classes_with_base=classes_with_base)
- else:
- cur_fail, cur_noticed = examine_stream(f, out_classes_with_base=classes_with_base)
-
- if not previous_file is None:
- with previous_file as f:
- if base_previous_file:
- with base_previous_file as base_f:
- prev_fail, prev_noticed = examine_stream(f, base_f,
- in_classes_with_base=classes_with_base)
- else:
- prev_fail, prev_noticed = examine_stream(f, in_classes_with_base=classes_with_base)
-
- # ignore errors from previous API level
- for p in prev_fail:
- if p in cur_fail:
- del cur_fail[p]
-
- # ignore classes unchanged from previous API level
- for k, v in prev_noticed.iteritems():
- if k in cur_noticed and v == cur_noticed[k]:
- del cur_noticed[k]
-
- """
- # NOTE: disabled because of memory pressure
- # look for compatibility issues
- compat_fail = verify_compat(cur, prev)
-
- print "%s API compatibility issues %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), format(reset=True)))
- for f in sorted(compat_fail):
- print compat_fail[f]
- print
- """
-
- # ignore everything but the given filters, if provided
- if filters:
- cur_fail = dict([(key, failure) for key, failure in cur_fail.iteritems()
- if match_filter(filters, failure.clazz.fullname)])
-
- if args['show_noticed'] and len(cur_noticed) != 0:
- print "%s API changes noticed %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), format(reset=True)))
- for f in sorted(cur_noticed.keys()):
- print f
- print
-
- if len(cur_fail) != 0:
- print "%s API style issues: %s %s" % ((format(fg=WHITE, bg=BLUE, bold=True),
- title, format(reset=True)))
- for f in filters:
- print "%s filter: %s %s" % ((format(fg=WHITE, bg=BLUE, bold=True),
- f, format(reset=True)))
- print
- for f in sorted(cur_fail):
- print cur_fail[f]
- print
- print "%d errors" % len(cur_fail)
- sys.exit(77)
-
-if __name__ == "__main__":
- try:
- main()
- except KeyboardInterrupt:
- sys.exit(1)
diff --git a/tools/apilint/apilint_sha.sh b/tools/apilint/apilint_sha.sh
deleted file mode 100755
index 2a45b10392d7..000000000000
--- a/tools/apilint/apilint_sha.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-if git show --name-only --pretty=format: $1 | grep api/ > /dev/null; then
- python tools/apilint/apilint.py <(git show $1:api/current.txt) <(git show $1^:api/current.txt)
-fi
diff --git a/tools/apilint/apilint_sha_system.sh b/tools/apilint/apilint_sha_system.sh
deleted file mode 100755
index 8538a3d904f5..000000000000
--- a/tools/apilint/apilint_sha_system.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/bash
-
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the 'License');
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an 'AS IS' BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-if git show --name-only --pretty=format: $1 | grep api/ > /dev/null; then
- python tools/apilint/apilint.py \
- --base-current <(git show $1:api/current.txt) \
- --base-previous <(git show $1^:api/current.txt) \
- <(git show $1:api/system-current.txt) \
- <(git show $1^:api/system-current.txt)
-fi
diff --git a/tools/apilint/apilint_stats.sh b/tools/apilint/apilint_stats.sh
deleted file mode 100755
index 052d9a5265fe..000000000000
--- a/tools/apilint/apilint_stats.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-API=28
-while [ $API -gt 14 ]; do
- echo "# Changes in API $((API))"
- python tools/apilint/apilint.py --show-stats ../../prebuilts/sdk/$((API))/public/api/android.txt ../../prebuilts/sdk/$((API-1))/public/api/android.txt
- let API=API-1
-done
diff --git a/tools/apilint/apilint_test.py b/tools/apilint/apilint_test.py
deleted file mode 100644
index 811cb9aa23d5..000000000000
--- a/tools/apilint/apilint_test.py
+++ /dev/null
@@ -1,414 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the 'License');
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an 'AS IS' BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import unittest
-
-import apilint
-
-def cls(pkg, name):
- return apilint.Class(apilint.Package(999, "package %s {" % pkg, None), 999,
- "public final class %s {" % name, None)
-
-_ri = apilint._retry_iterator
-
-c1 = cls("android.app", "ActivityManager")
-c2 = cls("android.app", "Notification")
-c3 = cls("android.app", "Notification.Action")
-c4 = cls("android.graphics", "Bitmap")
-
-class UtilTests(unittest.TestCase):
- def test_retry_iterator(self):
- it = apilint._retry_iterator([1, 2, 3, 4])
- self.assertEqual(it.next(), 1)
- self.assertEqual(it.next(), 2)
- self.assertEqual(it.next(), 3)
- it.send("retry")
- self.assertEqual(it.next(), 3)
- self.assertEqual(it.next(), 4)
- with self.assertRaises(StopIteration):
- it.next()
-
- def test_retry_iterator_one(self):
- it = apilint._retry_iterator([1])
- self.assertEqual(it.next(), 1)
- it.send("retry")
- self.assertEqual(it.next(), 1)
- with self.assertRaises(StopIteration):
- it.next()
-
- def test_retry_iterator_one(self):
- it = apilint._retry_iterator([1])
- self.assertEqual(it.next(), 1)
- it.send("retry")
- self.assertEqual(it.next(), 1)
- with self.assertRaises(StopIteration):
- it.next()
-
- def test_skip_to_matching_class_found(self):
- it = _ri([c1, c2, c3, c4])
- self.assertEquals(apilint._skip_to_matching_class(it, c3),
- c3)
- self.assertEqual(it.next(), c4)
-
- def test_skip_to_matching_class_not_found(self):
- it = _ri([c1, c2, c3, c4])
- self.assertEquals(apilint._skip_to_matching_class(it, cls("android.content", "ContentProvider")),
- None)
- self.assertEqual(it.next(), c4)
-
- def test_yield_until_matching_class_found(self):
- it = _ri([c1, c2, c3, c4])
- self.assertEquals(list(apilint._yield_until_matching_class(it, c3)),
- [c1, c2])
- self.assertEqual(it.next(), c4)
-
- def test_yield_until_matching_class_not_found(self):
- it = _ri([c1, c2, c3, c4])
- self.assertEquals(list(apilint._yield_until_matching_class(it, cls("android.content", "ContentProvider"))),
- [c1, c2, c3])
- self.assertEqual(it.next(), c4)
-
- def test_yield_until_matching_class_None(self):
- it = _ri([c1, c2, c3, c4])
- self.assertEquals(list(apilint._yield_until_matching_class(it, None)),
- [c1, c2, c3, c4])
-
-
-faulty_current_txt = """
-// Signature format: 2.0
-package android.app {
- public final class Activity {
- }
-
- public final class WallpaperColors implements android.os.Parcelable {
- ctor public WallpaperColors(@NonNull android.os.Parcel);
- method public int describeContents();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
- }
-}
-""".strip().split('\n')
-
-ok_current_txt = """
-// Signature format: 2.0
-package android.app {
- public final class Activity {
- }
-
- public final class WallpaperColors implements android.os.Parcelable {
- ctor public WallpaperColors();
- method public int describeContents();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
- }
-}
-""".strip().split('\n')
-
-system_current_txt = """
-// Signature format: 2.0
-package android.app {
- public final class WallpaperColors implements android.os.Parcelable {
- method public int getSomething();
- }
-}
-""".strip().split('\n')
-
-
-
-class BaseFileTests(unittest.TestCase):
- def test_base_file_avoids_errors(self):
- failures, _ = apilint.examine_stream(system_current_txt, ok_current_txt)
- self.assertEquals(failures, {})
-
- def test_class_with_base_finds_same_errors(self):
- failures_with_classes_with_base, _ = apilint.examine_stream("", faulty_current_txt,
- in_classes_with_base=[cls("android.app", "WallpaperColors")])
- failures_with_system_txt, _ = apilint.examine_stream(system_current_txt, faulty_current_txt)
-
- self.assertEquals(failures_with_classes_with_base.keys(), failures_with_system_txt.keys())
-
- def test_classes_with_base_is_emited(self):
- classes_with_base = []
- _, _ = apilint.examine_stream(system_current_txt, faulty_current_txt,
- out_classes_with_base=classes_with_base)
- self.assertEquals(map(lambda x: x.fullname, classes_with_base), ["android.app.WallpaperColors"])
-
-class ParseV2Stream(unittest.TestCase):
- def test_field_kinds(self):
- api = apilint._parse_stream("""
-// Signature format: 2.0
-package android {
- public enum SomeEnum {
- enum_constant public static final android.SomeEnum ENUM_CONST;
- field public static final int FIELD_CONST;
- property public final int someProperty;
- ctor public SomeEnum();
- method public Object? getObject();
- }
-}
- """.strip().split('\n'))
-
- self.assertEquals(api['android.SomeEnum'].fields[0].split[0], 'enum_constant')
- self.assertEquals(api['android.SomeEnum'].fields[1].split[0], 'field')
- self.assertEquals(api['android.SomeEnum'].fields[2].split[0], 'property')
- self.assertEquals(api['android.SomeEnum'].ctors[0].split[0], 'ctor')
- self.assertEquals(api['android.SomeEnum'].methods[0].split[0], 'method')
-
-class ParseV3Stream(unittest.TestCase):
- def test_field_kinds(self):
- api = apilint._parse_stream("""
-// Signature format: 3.0
-package a {
-
- public final class ContextKt {
- method public static inline <reified T> T! getSystemService(android.content.Context);
- method public static inline void withStyledAttributes(android.content.Context, android.util.AttributeSet? set = null, int[] attrs, @AttrRes int defStyleAttr = 0, @StyleRes int defStyleRes = 0, kotlin.jvm.functions.Function1<? super android.content.res.TypedArray,kotlin.Unit> block);
- }
-}
- """.strip().split('\n'))
- self.assertEquals(api['a.ContextKt'].methods[0].name, 'getSystemService')
- self.assertEquals(api['a.ContextKt'].methods[0].split[:4], ['method', 'public', 'static', 'inline'])
- self.assertEquals(api['a.ContextKt'].methods[1].name, 'withStyledAttributes')
- self.assertEquals(api['a.ContextKt'].methods[1].split[:4], ['method', 'public', 'static', 'inline'])
-
-class V2TokenizerTests(unittest.TestCase):
- def _test(self, raw, expected):
- self.assertEquals(apilint.V2Tokenizer(raw).tokenize(), expected)
-
- def test_simple(self):
- self._test(" method public some.Type someName(some.Argument arg, int arg);",
- ['method', 'public', 'some.Type', 'someName', '(', 'some.Argument',
- 'arg', ',', 'int', 'arg', ')', ';'])
- self._test("class Some.Class extends SomeOther {",
- ['class', 'Some.Class', 'extends', 'SomeOther', '{'])
-
- def test_varargs(self):
- self._test("name(String...)",
- ['name', '(', 'String', '...', ')'])
-
- def test_kotlin(self):
- self._test("String? name(String!...)",
- ['String', '?', 'name', '(', 'String', '!', '...', ')'])
-
- def test_annotation(self):
- self._test("method @Nullable public void name();",
- ['method', '@', 'Nullable', 'public', 'void', 'name', '(', ')', ';'])
-
- def test_annotation_args(self):
- self._test("@Some(val=1, other=2) class Class {",
- ['@', 'Some', '(', 'val', '=', '1', ',', 'other', '=', '2', ')',
- 'class', 'Class', '{'])
- def test_comment(self):
- self._test("some //comment", ['some'])
-
- def test_strings(self):
- self._test(r'"" "foo" "\"" "\\"', ['""', '"foo"', r'"\""', r'"\\"'])
-
- def test_at_interface(self):
- self._test("public @interface Annotation {",
- ['public', '@interface', 'Annotation', '{'])
-
- def test_array_type(self):
- self._test("int[][]", ['int', '[]', '[]'])
-
- def test_generics(self):
- self._test("<>foobar<A extends Object>",
- ['<', '>', 'foobar', '<', 'A', 'extends', 'Object', '>'])
-
-class V2ParserTests(unittest.TestCase):
- def _cls(self, raw):
- pkg = apilint.Package(999, "package pkg {", None)
- return apilint.Class(pkg, 1, raw, '', sig_format=2)
-
- def _method(self, raw, cls=None):
- if not cls:
- cls = self._cls("class Class {")
- return apilint.Method(cls, 1, raw, '', sig_format=2)
-
- def _field(self, raw):
- cls = self._cls("class Class {")
- return apilint.Field(cls, 1, raw, '', sig_format=2)
-
- def test_parse_package(self):
- pkg = apilint.Package(999, "package wifi.p2p {", None)
- self.assertEquals("wifi.p2p", pkg.name)
-
- def test_class(self):
- cls = self._cls("@Deprecated @IntRange(from=1, to=2) public static abstract class Some.Name extends Super<Class> implements Interface<Class> {")
- self.assertTrue('deprecated' in cls.split)
- self.assertTrue('static' in cls.split)
- self.assertTrue('abstract' in cls.split)
- self.assertTrue('class' in cls.split)
- self.assertEquals('Super', cls.extends)
- self.assertEquals('Interface', cls.implements)
- self.assertEquals('pkg.Some.Name', cls.fullname)
-
- def test_enum(self):
- cls = self._cls("public enum Some.Name {")
- self._field("enum_constant public static final android.ValueType COLOR;")
-
- def test_interface(self):
- cls = self._cls("@Deprecated @IntRange(from=1, to=2) public interface Some.Name extends Interface<Class> {")
- self.assertTrue('deprecated' in cls.split)
- self.assertTrue('interface' in cls.split)
- self.assertEquals('Interface', cls.extends)
- self.assertEquals('Interface', cls.implements)
- self.assertEquals('pkg.Some.Name', cls.fullname)
-
- def test_at_interface(self):
- cls = self._cls("@java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface SuppressLint {")
- self.assertTrue('@interface' in cls.split)
- self.assertEquals('pkg.SuppressLint', cls.fullname)
-
- def test_parse_method(self):
- m = self._method("method @Deprecated public static native <T> Class<T>[][] name("
- + "Class<T[]>[][], Class<T[][][]>[][]...) throws Exception, T;")
- self.assertTrue('static' in m.split)
- self.assertTrue('public' in m.split)
- self.assertTrue('method' in m.split)
- self.assertTrue('native' in m.split)
- self.assertTrue('deprecated' in m.split)
- self.assertEquals('java.lang.Class[][]', m.typ)
- self.assertEquals('name', m.name)
- self.assertEquals(['java.lang.Class[][]', 'java.lang.Class[][]...'], m.args)
- self.assertEquals(['java.lang.Exception', 'T'], m.throws)
-
- def test_ctor(self):
- m = self._method("ctor @Deprecated <T> ClassName();")
- self.assertTrue('ctor' in m.split)
- self.assertTrue('deprecated' in m.split)
- self.assertEquals('ctor', m.typ)
- self.assertEquals('ClassName', m.name)
-
- def test_parse_annotation_method(self):
- cls = self._cls("@interface Annotation {")
- self._method('method abstract String category() default "";', cls=cls)
- self._method('method abstract boolean deepExport() default false;', cls=cls)
- self._method('method abstract ViewDebug.FlagToString[] flagMapping() default {};', cls=cls)
- self._method('method abstract ViewDebug.FlagToString[] flagMapping() default (double)java.lang.Float.NEGATIVE_INFINITY;', cls=cls)
-
- def test_parse_string_field(self):
- f = self._field('field @Deprecated public final String SOME_NAME = "value";')
- self.assertTrue('field' in f.split)
- self.assertTrue('deprecated' in f.split)
- self.assertTrue('final' in f.split)
- self.assertEquals('java.lang.String', f.typ)
- self.assertEquals('SOME_NAME', f.name)
- self.assertEquals('value', f.value)
-
- def test_parse_field(self):
- f = self._field('field public Object SOME_NAME;')
- self.assertTrue('field' in f.split)
- self.assertEquals('java.lang.Object', f.typ)
- self.assertEquals('SOME_NAME', f.name)
- self.assertEquals(None, f.value)
-
- def test_parse_int_field(self):
- f = self._field('field public int NAME = 123;')
- self.assertTrue('field' in f.split)
- self.assertEquals('int', f.typ)
- self.assertEquals('NAME', f.name)
- self.assertEquals('123', f.value)
-
- def test_parse_quotient_field(self):
- f = self._field('field public int NAME = (0.0/0.0);')
- self.assertTrue('field' in f.split)
- self.assertEquals('int', f.typ)
- self.assertEquals('NAME', f.name)
- self.assertEquals('( 0.0 / 0.0 )', f.value)
-
- def test_kotlin_types(self):
- self._field('field public List<Integer[]?[]!>?[]![]? NAME;')
- self._method("method <T?> Class<T!>?[]![][]? name(Type!, Type argname,"
- + "Class<T?>[][]?[]!...!) throws Exception, T;")
- self._method("method <T> T name(T a = 1, T b = A(1), Lambda f = { false }, N? n = null, "
- + """double c = (1/0), float d = 1.0f, String s = "heyo", char c = 'a');""")
-
- def test_kotlin_operator(self):
- self._method('method public operator void unaryPlus(androidx.navigation.NavDestination);')
- self._method('method public static operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, @IdRes int id);')
- self._method('method public static operator <T> T get(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<T> clazz);')
-
- def test_kotlin_property(self):
- self._field('property public VM value;')
- self._field('property public final String? action;')
-
- def test_kotlin_varargs(self):
- self._method('method public void error(int p = "42", Integer int2 = "null", int p1 = "42", vararg String args);')
-
- def test_kotlin_default_values(self):
- self._method('method public void foo(String! = null, String! = "Hello World", int = 42);')
- self._method('method void method(String, String firstArg = "hello", int secondArg = "42", String thirdArg = "world");')
- self._method('method void method(String, String firstArg = "hello", int secondArg = "42");')
- self._method('method void method(String, String firstArg = "hello");')
- self._method('method void edit(android.Type, boolean commit = false, Function1<? super Editor,kotlin.Unit> action);')
- self._method('method <K, V> LruCache<K,V> lruCache(int maxSize, Function2<? super K,? super V,java.lang.Integer> sizeOf = { _, _ -> 1 }, Function1<? extends V> create = { (V)null }, Function4<kotlin.Unit> onEntryRemoved = { _, _, _, _ -> });')
- self._method('method android.Bitmap? drawToBitmap(android.View, android.Config config = android.graphics.Bitmap.Config.ARGB_8888);')
- self._method('method void emptyLambda(Function0<kotlin.Unit> sizeOf = {});')
- self._method('method void method1(int p = 42, Integer? int2 = null, int p1 = 42, String str = "hello world", java.lang.String... args);')
- self._method('method void method2(int p, int int2 = (2 * int) * some.other.pkg.Constants.Misc.SIZE);')
- self._method('method void method3(String str, int p, int int2 = double(int) + str.length);')
- self._method('method void print(test.pkg.Foo foo = test.pkg.Foo());')
-
- def test_type_use_annotation(self):
- self._method('method public static int codePointAt(char @NonNull [], int);')
- self._method('method @NonNull public java.util.Set<java.util.Map.@NonNull Entry<K,V>> entrySet();')
-
- m = self._method('method @NonNull public java.lang.annotation.@NonNull Annotation @NonNull [] getAnnotations();')
- self.assertEquals('java.lang.annotation.Annotation[]', m.typ)
-
- m = self._method('method @NonNull public abstract java.lang.annotation.@NonNull Annotation @NonNull [] @NonNull [] getParameterAnnotations();')
- self.assertEquals('java.lang.annotation.Annotation[][]', m.typ)
-
- m = self._method('method @NonNull public @NonNull String @NonNull [] split(@NonNull String, int);')
- self.assertEquals('java.lang.String[]', m.typ)
-
-class PackageTests(unittest.TestCase):
- def _package(self, raw):
- return apilint.Package(123, raw, "blame")
-
- def test_regular_package(self):
- p = self._package("package an.pref.int {")
- self.assertEquals('an.pref.int', p.name)
-
- def test_annotation_package(self):
- p = self._package("package @RestrictTo(a.b.C) an.pref.int {")
- self.assertEquals('an.pref.int', p.name)
-
- def test_multi_annotation_package(self):
- p = self._package("package @Rt(a.b.L_G_P) @RestrictTo(a.b.C) an.pref.int {")
- self.assertEquals('an.pref.int', p.name)
-
-class FilterTests(unittest.TestCase):
- def test_filter_match_prefix(self):
- self.assertTrue(apilint.match_filter(["a"], "a.B"))
- self.assertTrue(apilint.match_filter(["a.B"], "a.B.C"))
-
- def test_filter_dont_match_prefix(self):
- self.assertFalse(apilint.match_filter(["c"], "a.B"))
- self.assertFalse(apilint.match_filter(["a."], "a.B"))
- self.assertFalse(apilint.match_filter(["a.B."], "a.B.C"))
-
- def test_filter_match_exact(self):
- self.assertTrue(apilint.match_filter(["a.B"], "a.B"))
-
- def test_filter_dont_match_exact(self):
- self.assertFalse(apilint.match_filter([""], "a.B"))
- self.assertFalse(apilint.match_filter(["a.C"], "a.B"))
- self.assertFalse(apilint.match_filter(["a.C"], "a.B"))
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/tools/codegen/src/com/android/codegen/FieldInfo.kt b/tools/codegen/src/com/android/codegen/FieldInfo.kt
index ed35a1dfc599..ebfbbd8163b5 100644
--- a/tools/codegen/src/com/android/codegen/FieldInfo.kt
+++ b/tools/codegen/src/com/android/codegen/FieldInfo.kt
@@ -93,6 +93,8 @@ data class FieldInfo(
// Generic args
val isArray = Type.endsWith("[]")
val isList = FieldClass == "List" || FieldClass == "ArrayList"
+ val isMap = FieldClass == "Map" || FieldClass == "ArrayMap"
+ || FieldClass == "HashMap" || FieldClass == "LinkedHashMap"
val fieldBit = bitAtExpr(index)
var isLast = false
val isFinal = fieldAst.isFinal
@@ -197,7 +199,7 @@ data class FieldInfo(
listOf("String", "CharSequence", "Exception", "Size", "SizeF", "Bundle",
"FileDescriptor", "SparseBooleanArray", "SparseIntArray", "SparseArray") ->
FieldClass
- FieldClass == "Map" && fieldTypeGenegicArgs[0] == "String" -> "Map"
+ isMap && fieldTypeGenegicArgs[0] == "String" -> "Map"
isArray -> when {
FieldInnerType!! in (PRIMITIVE_TYPES + "String") -> FieldInnerType + "Array"
isBinder(FieldInnerType) -> "BinderArray"
diff --git a/tools/codegen/src/com/android/codegen/Generators.kt b/tools/codegen/src/com/android/codegen/Generators.kt
index c25d0c74f251..dc1f4c50abc4 100644
--- a/tools/codegen/src/com/android/codegen/Generators.kt
+++ b/tools/codegen/src/com/android/codegen/Generators.kt
@@ -343,7 +343,7 @@ private fun ClassPrinter.generateBuilderSetters(visibility: String) {
}
}
- if (FieldClass.endsWith("Map") && FieldInnerType != null) {
+ if (isMap && FieldInnerType != null) {
generateBuilderMethod(
name = adderName,
defVisibility = visibility,
@@ -351,7 +351,7 @@ private fun ClassPrinter.generateBuilderSetters(visibility: String) {
paramNames = listOf("key", "value"),
genJavadoc = { +javadocSeeSetter }) {
!singularNameCustomizationHint
- +"if ($name == null) $setterName(new $LinkedHashMap());"
+ +"if ($name == null) $setterName(new ${if (FieldClass == "Map") LinkedHashMap else FieldClass}());"
+"$name.put(key, value);"
+"return$maybeCast this;"
}
@@ -507,7 +507,8 @@ fun ClassPrinter.generateParcelable() {
// Create container if any
val containerInitExpr = when {
- FieldClass.endsWith("Map") -> "new $LinkedHashMap<>()"
+ FieldClass == "Map" -> "new $LinkedHashMap<>()"
+ isMap -> "new $FieldClass()"
FieldClass == "List" || FieldClass == "ArrayList" ->
"new ${classRef("java.util.ArrayList")}<>()"
else -> ""
diff --git a/tools/codegen/src/com/android/codegen/SharedConstants.kt b/tools/codegen/src/com/android/codegen/SharedConstants.kt
index 339057f24833..85c832fcf34f 100644
--- a/tools/codegen/src/com/android/codegen/SharedConstants.kt
+++ b/tools/codegen/src/com/android/codegen/SharedConstants.kt
@@ -1,7 +1,7 @@
package com.android.codegen
const val CODEGEN_NAME = "codegen"
-const val CODEGEN_VERSION = "1.0.12"
+const val CODEGEN_VERSION = "1.0.13"
const val CANONICAL_BUILDER_CLASS = "Builder"
const val BASE_BUILDER_CLASS = "BaseBuilder"
diff --git a/wifi/java/android/net/wifi/ISoftApCallback.aidl b/wifi/java/android/net/wifi/ISoftApCallback.aidl
index 8a252dd1e447..452a655edc7b 100644
--- a/wifi/java/android/net/wifi/ISoftApCallback.aidl
+++ b/wifi/java/android/net/wifi/ISoftApCallback.aidl
@@ -15,6 +15,7 @@
*/
package android.net.wifi;
+import android.net.wifi.SoftApInfo;
import android.net.wifi.WifiClient;
@@ -43,4 +44,11 @@ oneway interface ISoftApCallback
* @param clients the currently connected clients
*/
void onConnectedClientsChanged(in List<WifiClient> clients);
+
+ /**
+ * Service to manager callback providing information of softap.
+ *
+ * @param softApInfo is the softap information. {@link SoftApInfo}
+ */
+ void onInfoChanged(in SoftApInfo softApInfo);
}
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index aa895a61df9b..ed1a2f9f16ca 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -549,6 +549,7 @@ public class ScanResult implements Parcelable {
/**
* Extension IDs
*/
+ public static final int EID_EXT_HE_CAPABILITIES = 35;
public static final int EID_EXT_HE_OPERATION = 36;
@UnsupportedAppUsage
diff --git a/wifi/java/android/net/wifi/SoftApInfo.aidl b/wifi/java/android/net/wifi/SoftApInfo.aidl
new file mode 100644
index 000000000000..d4551cfac044
--- /dev/null
+++ b/wifi/java/android/net/wifi/SoftApInfo.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+parcelable SoftApInfo;
+
diff --git a/wifi/java/android/net/wifi/SoftApInfo.java b/wifi/java/android/net/wifi/SoftApInfo.java
new file mode 100644
index 000000000000..375a9774f570
--- /dev/null
+++ b/wifi/java/android/net/wifi/SoftApInfo.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * A class representing information about SoftAp.
+ * {@see WifiManager}
+ *
+ * @hide
+ */
+@SystemApi
+public final class SoftApInfo implements Parcelable {
+
+ /**
+ * AP Channel bandwidth is invalid.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_INVALID = 0;
+
+ /**
+ * AP Channel bandwidth is 20 MHZ but no HT.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_20MHZ_NOHT = 1;
+
+ /**
+ * AP Channel bandwidth is 20 MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_20MHZ = 2;
+
+ /**
+ * AP Channel bandwidth is 40 MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_40MHZ = 3;
+
+ /**
+ * AP Channel bandwidth is 80 MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_80MHZ = 4;
+
+ /**
+ * AP Channel bandwidth is 160 MHZ, but 80MHZ + 80MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 5;
+
+ /**
+ * AP Channel bandwidth is 160 MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_160MHZ = 6;
+
+ /**
+ * @hide
+ */
+ @IntDef(prefix = { "CHANNEL_WIDTH_" }, value = {
+ CHANNEL_WIDTH_INVALID,
+ CHANNEL_WIDTH_20MHZ_NOHT,
+ CHANNEL_WIDTH_20MHZ,
+ CHANNEL_WIDTH_40MHZ,
+ CHANNEL_WIDTH_80MHZ,
+ CHANNEL_WIDTH_80MHZ_PLUS_MHZ,
+ CHANNEL_WIDTH_160MHZ,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Bandwidth {}
+
+
+ /** The frequency which AP resides on. */
+ private int mFrequency = 0;
+
+ @Bandwidth
+ private int mBandwidth = CHANNEL_WIDTH_INVALID;
+
+ /**
+ * Get the frequency which AP resides on.
+ */
+ public int getFrequency() {
+ return mFrequency;
+ }
+
+ /**
+ * Set the frequency which AP resides on.
+ * @hide
+ */
+ public void setFrequency(int freq) {
+ mFrequency = freq;
+ }
+
+ /**
+ * Get AP Channel bandwidth.
+ *
+ * @return One of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ},
+ * {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ},
+ * {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ} or {@link #CHANNEL_WIDTH_UNKNOWN}.
+ */
+ @Bandwidth
+ public int getBandwidth() {
+ return mBandwidth;
+ }
+
+ /**
+ * Set AP Channel bandwidth.
+ * @hide
+ */
+ public void setBandwidth(@Bandwidth int bandwidth) {
+ mBandwidth = bandwidth;
+ }
+
+ /**
+ * @hide
+ */
+ public SoftApInfo(@Nullable SoftApInfo source) {
+ if (source != null) {
+ mFrequency = source.mFrequency;
+ mBandwidth = source.mBandwidth;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public SoftApInfo() {
+ }
+
+ @Override
+ /** Implement the Parcelable interface. */
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ /** Implement the Parcelable interface */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mFrequency);
+ dest.writeInt(mBandwidth);
+ }
+
+ @NonNull
+ /** Implement the Parcelable interface */
+ public static final Creator<SoftApInfo> CREATOR = new Creator<SoftApInfo>() {
+ public SoftApInfo createFromParcel(Parcel in) {
+ SoftApInfo info = new SoftApInfo();
+ info.mFrequency = in.readInt();
+ info.mBandwidth = in.readInt();
+ return info;
+ }
+
+ public SoftApInfo[] newArray(int size) {
+ return new SoftApInfo[size];
+ }
+ };
+
+ @NonNull
+ @Override
+ public String toString() {
+ return "SoftApInfo{"
+ + "bandwidth= " + mBandwidth
+ + ",frequency= " + mFrequency
+ + '}';
+ }
+
+ @Override
+ public boolean equals(@NonNull Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SoftApInfo)) return false;
+ SoftApInfo softApInfo = (SoftApInfo) o;
+ return mFrequency == softApInfo.mFrequency
+ && mBandwidth == softApInfo.mBandwidth;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mFrequency, mBandwidth);
+ }
+}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 07831c71b0d3..8108fef5d3ee 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -3315,6 +3315,15 @@ public class WifiManager {
* @param clients the currently connected clients
*/
void onConnectedClientsChanged(@NonNull List<WifiClient> clients);
+
+ /**
+ * Called when information of softap changes.
+ *
+ * @param softApInfo is the softap information. {@link SoftApInfo}
+ */
+ default void onInfoChanged(@NonNull SoftApInfo softApInfo) {
+ // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI.
+ }
}
/**
@@ -3354,6 +3363,16 @@ public class WifiManager {
mCallback.onConnectedClientsChanged(clients);
});
}
+
+ @Override
+ public void onInfoChanged(SoftApInfo softApInfo) {
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, "SoftApCallbackProxy: onInfoChange: softApInfo=" + softApInfo);
+ }
+ mHandler.post(() -> {
+ mCallback.onInfoChanged(softApInfo);
+ });
+ }
}
/**
diff --git a/wifi/java/android/net/wifi/rtt/ResponderConfig.java b/wifi/java/android/net/wifi/rtt/ResponderConfig.java
index 64dfc3499aaf..be4eeccd0c31 100644
--- a/wifi/java/android/net/wifi/rtt/ResponderConfig.java
+++ b/wifi/java/android/net/wifi/rtt/ResponderConfig.java
@@ -16,6 +16,8 @@
package android.net.wifi.rtt;
+import static android.net.wifi.ScanResult.InformationElement.EID_EXTENSION_PRESENT;
+import static android.net.wifi.ScanResult.InformationElement.EID_EXT_HE_CAPABILITIES;
import static android.net.wifi.ScanResult.InformationElement.EID_HT_CAPABILITIES;
import static android.net.wifi.ScanResult.InformationElement.EID_VHT_CAPABILITIES;
@@ -106,7 +108,7 @@ public final class ResponderConfig implements Parcelable {
public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4;
/** @hide */
- @IntDef({PREAMBLE_LEGACY, PREAMBLE_HT, PREAMBLE_VHT})
+ @IntDef({PREAMBLE_LEGACY, PREAMBLE_HT, PREAMBLE_VHT, PREAMBLE_HE})
@Retention(RetentionPolicy.SOURCE)
public @interface PreambleType {
}
@@ -126,6 +128,10 @@ public final class ResponderConfig implements Parcelable {
*/
public static final int PREAMBLE_VHT = 2;
+ /**
+ * Preamble type: HE.
+ */
+ public static final int PREAMBLE_HE = 3;
/**
* The MAC address of the Responder. Will be null if a Wi-Fi Aware peer identifier (the
@@ -307,14 +313,21 @@ public final class ResponderConfig implements Parcelable {
if (scanResult.informationElements != null && scanResult.informationElements.length != 0) {
boolean htCapabilitiesPresent = false;
boolean vhtCapabilitiesPresent = false;
+ boolean heCapabilitiesPresent = false;
+
for (ScanResult.InformationElement ie : scanResult.informationElements) {
if (ie.id == EID_HT_CAPABILITIES) {
htCapabilitiesPresent = true;
} else if (ie.id == EID_VHT_CAPABILITIES) {
vhtCapabilitiesPresent = true;
+ } else if (ie.id == EID_EXTENSION_PRESENT && ie.idExt == EID_EXT_HE_CAPABILITIES) {
+ heCapabilitiesPresent = true;
}
}
- if (vhtCapabilitiesPresent) {
+
+ if (heCapabilitiesPresent) {
+ preamble = PREAMBLE_HE;
+ } else if (vhtCapabilitiesPresent) {
preamble = PREAMBLE_VHT;
} else if (htCapabilitiesPresent) {
preamble = PREAMBLE_HT;
diff --git a/wifi/tests/src/android/net/wifi/SoftApInfoTest.java b/wifi/tests/src/android/net/wifi/SoftApInfoTest.java
new file mode 100644
index 000000000000..929f3ab88fd8
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/SoftApInfoTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.os.Parcel;
+
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.SoftApInfo}.
+ */
+@SmallTest
+public class SoftApInfoTest {
+
+ /**
+ * Verifies copy constructor.
+ */
+ @Test
+ public void testCopyOperator() throws Exception {
+ SoftApInfo info = new SoftApInfo();
+ info.setFrequency(2412);
+ info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ);
+
+ SoftApInfo copiedInfo = new SoftApInfo(info);
+
+ assertEquals(info, copiedInfo);
+ assertEquals(info.hashCode(), copiedInfo.hashCode());
+ }
+
+ /**
+ * Verifies parcel serialization/deserialization.
+ */
+ @Test
+ public void testParcelOperation() throws Exception {
+ SoftApInfo info = new SoftApInfo();
+ info.setFrequency(2412);
+ info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ);
+
+ Parcel parcelW = Parcel.obtain();
+ info.writeToParcel(parcelW, 0);
+ byte[] bytes = parcelW.marshall();
+ parcelW.recycle();
+
+ Parcel parcelR = Parcel.obtain();
+ parcelR.unmarshall(bytes, 0, bytes.length);
+ parcelR.setDataPosition(0);
+ SoftApInfo fromParcel = SoftApInfo.CREATOR.createFromParcel(parcelR);
+
+ assertEquals(info, fromParcel);
+ assertEquals(info.hashCode(), fromParcel.hashCode());
+ }
+
+}
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index d2516a33fead..14e994cf0f08 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -97,6 +97,8 @@ public class WifiManagerTest {
private static final String TEST_PACKAGE_NAME = "TestPackage";
private static final String TEST_COUNTRY_CODE = "US";
private static final String[] TEST_MAC_ADDRESSES = {"da:a1:19:0:0:0"};
+ private static final int TEST_AP_FREQUENCY = 2412;
+ private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ;
@Mock Context mContext;
@Mock android.net.wifi.IWifiManager mWifiService;
@@ -122,7 +124,6 @@ public class WifiManagerTest {
mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo);
when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME);
-
mWifiManager = new WifiManager(mContext, mWifiService, mLooper.getLooper());
verify(mWifiService).getVerboseLoggingLevel();
}
@@ -776,11 +777,34 @@ public class WifiManagerTest {
verify(mSoftApCallback).onConnectedClientsChanged(testClients);
}
+
+ /*
+ * Verify client-provided callback is being called through callback proxy
+ */
+ @Test
+ public void softApCallbackProxyCallsOnSoftApInfoChanged() throws Exception {
+ SoftApInfo testSoftApInfo = new SoftApInfo();
+ testSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
+ testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
+ ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
+ ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
+ mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+ verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+ anyInt());
+
+ callbackCaptor.getValue().onInfoChanged(testSoftApInfo);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback).onInfoChanged(testSoftApInfo);
+ }
+
/*
* Verify client-provided callback is being called through callback proxy on multiple events
*/
@Test
public void softApCallbackProxyCallsOnMultipleUpdates() throws Exception {
+ SoftApInfo testSoftApInfo = new SoftApInfo();
+ testSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
+ testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
@@ -790,11 +814,13 @@ public class WifiManagerTest {
final List<WifiClient> testClients = new ArrayList();
callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLING, 0);
callbackCaptor.getValue().onConnectedClientsChanged(testClients);
+ callbackCaptor.getValue().onInfoChanged(testSoftApInfo);
callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
mLooper.dispatchAll();
verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLING, 0);
verify(mSoftApCallback).onConnectedClientsChanged(testClients);
+ verify(mSoftApCallback).onInfoChanged(testSoftApInfo);
verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
}