summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp27
-rw-r--r--StubLibraries.bp49
-rw-r--r--apct-tests/perftests/contentcapture/Android.bp3
-rw-r--r--apct-tests/perftests/contentcapture/AndroidManifest.xml5
-rw-r--r--apct-tests/perftests/contentcapture/AndroidTest.xml32
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java4
-rw-r--r--api/current.txt20
-rw-r--r--api/module-lib-current.txt1
-rwxr-xr-xapi/system-current.txt3
-rw-r--r--api/test-current.txt1
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.cpp4
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.h3
-rw-r--r--cmds/statsd/Android.bp5
-rw-r--r--cmds/statsd/src/StatsLogProcessor.cpp3
-rw-r--r--cmds/statsd/src/hash.h1
-rw-r--r--cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp5
-rw-r--r--cmds/statsd/src/matchers/CombinationLogMatchingTracker.h2
-rw-r--r--cmds/statsd/src/matchers/LogMatchingTracker.h18
-rw-r--r--cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp6
-rw-r--r--cmds/statsd/src/matchers/SimpleLogMatchingTracker.h7
-rw-r--r--cmds/statsd/src/matchers/matcher_util.cpp9
-rw-r--r--cmds/statsd/src/matchers/matcher_util.h4
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.cpp32
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.h10
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp203
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/config_update_utils.h89
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp (renamed from cmds/statsd/src/metrics/metrics_manager_util.cpp)147
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h (renamed from cmds/statsd/src/metrics/metrics_manager_util.h)33
-rw-r--r--cmds/statsd/src/shell/ShellSubscriber.cpp4
-rw-r--r--cmds/statsd/tests/LogEntryMatcher_test.cpp28
-rw-r--r--cmds/statsd/tests/MetricsManager_test.cpp556
-rw-r--r--cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp69
-rw-r--r--cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp145
-rw-r--r--cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp382
-rw-r--r--cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp708
-rw-r--r--cmds/statsd/tests/statsd_test_util.cpp16
-rw-r--r--cmds/statsd/tests/statsd_test_util.h4
-rw-r--r--config/boot-image-profile.txt29
-rw-r--r--core/java/android/app/Activity.java6
-rw-r--r--core/java/android/app/ActivityThread.java60
-rw-r--r--core/java/android/app/ApplicationPackageManager.java3
-rw-r--r--core/java/android/app/ContentProviderHolder.java9
-rw-r--r--core/java/android/app/IActivityManager.aidl2
-rw-r--r--core/java/android/app/IApplicationThread.aidl3
-rw-r--r--core/java/android/app/IUiAutomationConnection.aidl2
-rw-r--r--core/java/android/app/Notification.java52
-rw-r--r--core/java/android/app/UiAutomation.java2
-rw-r--r--core/java/android/app/UiAutomationConnection.java12
-rw-r--r--core/java/android/app/backup/BackupAgent.java47
-rw-r--r--core/java/android/app/slice/SliceProvider.java5
-rw-r--r--core/java/android/app/timezonedetector/TimeZoneCapabilities.java33
-rw-r--r--core/java/android/app/timezonedetector/TimeZoneConfiguration.java35
-rw-r--r--core/java/android/app/usage/UsageEvents.java2
-rw-r--r--core/java/android/content/LocusId.java2
-rw-r--r--core/java/android/net/NetworkTemplate.java4
-rwxr-xr-xcore/java/android/os/Build.java14
-rw-r--r--core/java/android/os/INetworkManagementService.aidl4
-rw-r--r--core/java/android/os/Parcelable.java1
-rw-r--r--core/java/android/os/SystemClock.java9
-rw-r--r--core/java/android/permission/PermissionControllerService.java11
-rw-r--r--core/java/android/permission/PermissionManager.java27
-rw-r--r--core/java/android/view/ImeInsetsSourceConsumer.java10
-rw-r--r--core/java/android/view/SurfaceControl.java167
-rw-r--r--core/java/android/view/accessibility/IWindowMagnificationConnection.aidl8
-rw-r--r--core/java/android/view/inputmethod/BaseInputConnection.java20
-rw-r--r--core/java/android/view/textclassifier/TextClassificationSession.java90
-rw-r--r--core/java/android/widget/Editor.java82
-rw-r--r--core/java/android/widget/Magnifier.java53
-rw-r--r--core/java/com/android/internal/os/BinderCallsStats.java205
-rw-r--r--core/java/com/android/internal/os/BinderInternal.java3
-rw-r--r--core/java/com/android/internal/protolog/ProtoLogGroup.java (renamed from services/core/java/com/android/server/wm/ProtoLogGroup.java)18
-rw-r--r--core/java/com/android/internal/protolog/ProtoLogImpl.java (renamed from services/core/java/com/android/server/protolog/ProtoLogImpl.java)41
-rw-r--r--core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java (renamed from services/core/java/com/android/server/protolog/ProtoLogViewerConfigReader.java)17
-rw-r--r--core/java/com/android/internal/protolog/common/BitmaskConversionException.java (renamed from services/core/java/com/android/server/protolog/common/BitmaskConversionException.java)4
-rw-r--r--core/java/com/android/internal/protolog/common/IProtoLogGroup.java (renamed from services/core/java/com/android/server/protolog/common/IProtoLogGroup.java)4
-rw-r--r--core/java/com/android/internal/protolog/common/InvalidFormatStringException.java (renamed from services/core/java/com/android/server/protolog/common/InvalidFormatStringException.java)4
-rw-r--r--core/java/com/android/internal/protolog/common/LogDataType.java (renamed from services/core/java/com/android/server/protolog/common/LogDataType.java)4
-rw-r--r--core/java/com/android/internal/protolog/common/ProtoLog.java (renamed from services/core/java/com/android/server/protolog/common/ProtoLog.java)4
-rw-r--r--core/java/com/android/internal/util/ScreenshotHelper.java7
-rw-r--r--core/java/com/android/internal/util/StatLogger.java2
-rw-r--r--core/jni/android_os_SystemClock.cpp7
-rw-r--r--core/jni/android_view_SurfaceControl.cpp5
-rw-r--r--core/proto/android/app/settings_enums.proto35
-rw-r--r--core/proto/android/app/tvsettings_enums.proto6
-rw-r--r--core/proto/android/internal/protolog.proto (renamed from core/proto/android/server/protolog.proto)2
-rw-r--r--core/res/AndroidManifest.xml2
-rw-r--r--core/res/res/values-ca/strings.xml8
-rw-r--r--core/res/res/values-ne/strings.xml2
-rw-r--r--core/res/res/values/config.xml2
-rw-r--r--core/res/res/values/public.xml3
-rw-r--r--core/res/res/xml/power_profile.xml2
-rw-r--r--core/tests/coretests/src/android/app/WindowContextTest.java2
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java6
-rw-r--r--core/tests/coretests/src/android/app/timezonedetector/TimeZoneCapabilitiesTest.java20
-rw-r--r--core/tests/coretests/src/android/app/timezonedetector/TimeZoneConfigurationTest.java49
-rw-r--r--core/tests/coretests/src/android/view/WindowMetricsTest.java2
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java59
-rw-r--r--libs/hwui/renderthread/EglManager.cpp9
-rw-r--r--media/java/android/media/AudioDeviceInfo.java33
-rw-r--r--media/java/android/media/AudioDevicePort.java4
-rwxr-xr-xmedia/java/android/media/AudioManager.java20
-rw-r--r--media/java/android/media/AudioSystem.java30
-rw-r--r--media/java/android/media/MediaTranscodeManager.java67
-rw-r--r--media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java70
-rw-r--r--non-updatable-api/current.txt20
-rw-r--r--non-updatable-api/module-lib-current.txt1
-rw-r--r--non-updatable-api/system-current.txt1
-rw-r--r--packages/CarSystemUI/proguard.flags2
-rw-r--r--packages/CarSystemUI/samples/sample1/rro/Android.bp27
-rw-r--r--packages/CarSystemUI/samples/sample1/rro/AndroidManifest.xml24
-rw-r--r--packages/CarSystemUI/samples/sample1/rro/res/values/config.xml47
-rw-r--r--packages/CarSystemUI/samples/sample1/rro/res/xml/car_sysui_overlays.xml33
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarGlobalRootComponent.java (renamed from packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java)14
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java38
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java6
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java17
-rw-r--r--packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java35
-rw-r--r--packages/SettingsLib/res/values-fr/strings.xml6
-rw-r--r--packages/Shell/src/com/android/shell/Screenshooter.java28
-rw-r--r--packages/SystemUI/proguard.flags4
-rw-r--r--packages/SystemUI/res-keyguard/values/styles.xml1
-rw-r--r--packages/SystemUI/res/drawable-television/ic_volume_media.xml26
-rw-r--r--packages/SystemUI/res/drawable-television/ic_volume_media_low.xml26
-rw-r--r--packages/SystemUI/res/drawable-television/ic_volume_media_mute.xml27
-rw-r--r--packages/SystemUI/res/drawable/ic_volume_media_low.xml18
-rw-r--r--packages/SystemUI/res/drawable/tv_rect_shadow_rounded.xml (renamed from packages/SystemUI/res/drawable/tv_ring_white.xml)8
-rw-r--r--packages/SystemUI/res/drawable/tv_volume_dialog_background.xml (renamed from packages/SystemUI/res/drawable/tv_circle_dark.xml)10
-rw-r--r--packages/SystemUI/res/drawable/tv_volume_dialog_circle.xml (renamed from packages/SystemUI/res/drawable/tv_circle_white_translucent.xml)8
-rw-r--r--packages/SystemUI/res/layout-land-television/volume_dialog.xml10
-rw-r--r--packages/SystemUI/res/layout-land-television/volume_dialog_row.xml18
-rw-r--r--packages/SystemUI/res/layout-land/volume_dialog.xml2
-rw-r--r--packages/SystemUI/res/layout/tv_audio_recording_indicator.xml40
-rw-r--r--packages/SystemUI/res/layout/volume_dialog.xml2
-rw-r--r--packages/SystemUI/res/layout/volume_dialog_row.xml2
-rw-r--r--packages/SystemUI/res/values-af/strings.xml2
-rw-r--r--packages/SystemUI/res/values-am/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml3
-rw-r--r--packages/SystemUI/res/values-as/strings.xml3
-rw-r--r--packages/SystemUI/res/values-az/strings.xml3
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml3
-rw-r--r--packages/SystemUI/res/values-be/strings.xml3
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml3
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml9
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml3
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml3
-rw-r--r--packages/SystemUI/res/values-da/strings.xml3
-rw-r--r--packages/SystemUI/res/values-de/strings.xml9
-rw-r--r--packages/SystemUI/res/values-el/strings.xml3
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings.xml2
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml3
-rw-r--r--packages/SystemUI/res/values-es/strings.xml3
-rw-r--r--packages/SystemUI/res/values-et/strings.xml3
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml4
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml2
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml3
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml3
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml3
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml3
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml9
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml4
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml3
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml3
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml3
-rw-r--r--packages/SystemUI/res/values-in/strings.xml3
-rw-r--r--packages/SystemUI/res/values-is/strings.xml3
-rw-r--r--packages/SystemUI/res/values-it/strings.xml3
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml3
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml3
-rw-r--r--packages/SystemUI/res/values-km/strings.xml3
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml3
-rw-r--r--packages/SystemUI/res/values-land-television/dimens.xml5
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml3
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml3
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml3
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml3
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml3
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml3
-rw-r--r--packages/SystemUI/res/values-my/strings.xml2
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml17
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml3
-rw-r--r--packages/SystemUI/res/values-or/strings.xml9
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml9
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml3
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml2
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml2
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml3
-rw-r--r--packages/SystemUI/res/values-si/strings.xml2
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml3
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml3
-rw-r--r--packages/SystemUI/res/values-te/strings.xml3
-rw-r--r--packages/SystemUI/res/values-television/config.xml3
-rw-r--r--packages/SystemUI/res/values-television/styles.xml4
-rw-r--r--packages/SystemUI/res/values-th/strings.xml3
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml3
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml3
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml3
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml3
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml4
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml3
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml3
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml3
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml3
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml3
-rw-r--r--packages/SystemUI/res/values/colors_tv.xml6
-rw-r--r--packages/SystemUI/res/values/config.xml8
-rw-r--r--packages/SystemUI/res/values/donottranslate.xml2
-rw-r--r--packages/SystemUI/res/values/styles.xml3
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/ContextUtils.java28
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIApplication.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java272
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/appops/AppOpItem.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java91
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java (renamed from packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java)47
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SysUISingleton.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/WMModule.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/WMSingleton.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt131
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaData.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt38
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java58
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java69
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelfController.java122
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt31
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationShelfComponent.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java164
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java713
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java343
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioActivityObserver.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java160
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/MicrophoneForegroundServicesObserver.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/RecordAudioAppOpObserver.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java (renamed from packages/SystemUI/src/com/android/systemui/tv/TvSystemUIRootComponent.java)14
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvSystemUIFactory.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java165
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java83
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java41
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java15
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java363
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java39
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java107
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java29
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt122
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java34
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java10
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt93
-rw-r--r--services/Android.bp4
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java45
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java15
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/SaveUi.java9
-rw-r--r--services/backup/java/com/android/server/backup/UserBackupManagerService.java17
-rw-r--r--services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java7
-rw-r--r--services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java2
-rw-r--r--services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java26
-rw-r--r--services/backup/java/com/android/server/backup/utils/TarBackupReader.java2
-rw-r--r--services/core/Android.bp40
-rw-r--r--services/core/java/com/android/server/BinderCallsStatsService.java142
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java2
-rw-r--r--services/core/java/com/android/server/IpSecService.java2
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java36
-rw-r--r--services/core/java/com/android/server/PackageWatchdog.java7
-rw-r--r--services/core/java/com/android/server/VibratorService.java57
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java114
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerConstants.java23
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java61
-rw-r--r--services/core/java/com/android/server/am/ContentProviderHelper.java45
-rw-r--r--services/core/java/com/android/server/am/ContentProviderRecord.java47
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java11
-rw-r--r--services/core/java/com/android/server/am/ServiceRecord.java10
-rw-r--r--services/core/java/com/android/server/am/UserController.java19
-rwxr-xr-xservices/core/java/com/android/server/audio/AudioService.java83
-rw-r--r--services/core/java/com/android/server/connectivity/PermissionMonitor.java111
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java73
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java41
-rw-r--r--services/core/java/com/android/server/infra/AbstractMasterSystemService.java2
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java2
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java3
-rw-r--r--services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java2
-rw-r--r--services/core/java/com/android/server/location/LocationProviderManager.java2
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssLocationProvider.java18
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java23
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyLogger.java18
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java264
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java3
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java10
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java122
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceUtils.java16
-rw-r--r--services/core/java/com/android/server/pm/Settings.java111
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java37
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java37
-rw-r--r--services/core/java/com/android/server/pm/UserRestrictionsUtils.java5
-rw-r--r--services/core/java/com/android/server/pm/UserSystemPackageInstaller.java11
-rw-r--r--services/core/java/com/android/server/pm/permission/BasePermission.java4
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java310
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java31
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyService.java10
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java7
-rw-r--r--services/core/java/com/android/server/power/ThermalManagerService.java2
-rw-r--r--services/core/java/com/android/server/slice/SliceManagerService.java179
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java20
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java3
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java1
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java7
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java6
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java134
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java18
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java13
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java6
-rw-r--r--services/core/java/com/android/server/wm/AppTransitionController.java6
-rw-r--r--services/core/java/com/android/server/wm/BlackFrame.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayArea.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java36
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java4
-rw-r--r--services/core/java/com/android/server/wm/DragState.java6
-rw-r--r--services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java4
-rw-r--r--services/core/java/com/android/server/wm/InputMonitor.java4
-rw-r--r--services/core/java/com/android/server/wm/InsetsSourceProvider.java4
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java8
-rw-r--r--services/core/java/com/android/server/wm/RecentTasks.java22
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimation.java4
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimationController.java4
-rw-r--r--services/core/java/com/android/server/wm/RemoteAnimationController.java6
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java16
-rw-r--r--services/core/java/com/android/server/wm/ScreenRotationAnimation.java6
-rw-r--r--services/core/java/com/android/server/wm/Session.java4
-rw-r--r--services/core/java/com/android/server/wm/SurfaceFreezer.java4
-rw-r--r--services/core/java/com/android/server/wm/Task.java31
-rw-r--r--services/core/java/com/android/server/wm/TaskDisplayArea.java6
-rw-r--r--services/core/java/com/android/server/wm/TaskPositioner.java4
-rw-r--r--services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java4
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java3
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotSurface.java4
-rw-r--r--services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java8
-rw-r--r--services/core/java/com/android/server/wm/WindowContainerThumbnail.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java30
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerShellCommand.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java27
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java30
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java18
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfaceController.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowToken.java30
-rw-r--r--services/core/java/com/android/server/wm/WindowTracing.java2
-rw-r--r--services/core/jni/com_android_server_VibratorService.cpp240
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java1116
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java566
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java1613
-rw-r--r--services/incremental/IncrementalService.cpp3
-rw-r--r--services/systemcaptions/java/com/android/server/systemcaptions/SystemCaptionsManagerService.java3
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java16
-rw-r--r--services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-lists-allowlist-format.xml (renamed from services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-lists-whitelist-format.xml)0
-rw-r--r--services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-allowlisted-restrict-background-off.xml (renamed from services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-off.xml)0
-rw-r--r--services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-allowlisted-restrict-background-on.xml (renamed from services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-on.xml)0
-rw-r--r--services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-denylisted-restrict-background-off.xml (renamed from services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-off.xml)0
-rw-r--r--services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-denylisted-restrict-background-on.xml (renamed from services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-on.xml)0
-rw-r--r--services/tests/servicestests/src/com/android/server/VibratorServiceTest.java62
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java278
-rw-r--r--services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java146
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt5
-rw-r--r--services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java16
-rw-r--r--services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java41
-rw-r--r--services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java512
-rw-r--r--services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java8
-rw-r--r--services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java76
-rw-r--r--services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java4
-rw-r--r--services/tests/wmtests/Android.bp32
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java22
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java68
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java15
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java15
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java25
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java18
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java16
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskTests.java21
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java12
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java15
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java134
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java117
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java43
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java21
-rw-r--r--telephony/common/com/android/internal/telephony/CarrierAppUtils.java11
-rw-r--r--telephony/java/android/telephony/SmsManager.java14
-rw-r--r--tests/Internal/Android.bp1
-rw-r--r--tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java (renamed from services/tests/servicestests/src/com/android/server/protolog/ProtoLogImplTest.java)6
-rw-r--r--tests/Internal/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java (renamed from services/tests/servicestests/src/com/android/server/protolog/ProtoLogViewerConfigReaderTest.java)2
-rw-r--r--tests/Internal/src/com/android/internal/protolog/common/LogDataTypeTest.java (renamed from services/tests/servicestests/src/com/android/server/protolog/common/LogDataTypeTest.java)2
-rw-r--r--tests/RollbackTest/README.txt4
-rw-r--r--tests/StagedInstallTest/Android.bp3
-rw-r--r--tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java23
-rw-r--r--tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java58
-rw-r--r--tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java91
-rw-r--r--tests/net/java/com/android/server/connectivity/VpnTest.java22
-rw-r--r--tools/protologtool/Android.bp2
-rw-r--r--tools/protologtool/src/com/android/protolog/tool/LogParser.kt9
-rw-r--r--tools/protologtool/src/com/android/protolog/tool/ProtoLogGroupReader.kt2
-rw-r--r--tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt8
-rw-r--r--tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt2
-rw-r--r--tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt20
-rw-r--r--tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt4
-rw-r--r--wifi/api/system-current.txt2
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java26
-rw-r--r--wifi/java/android/net/wifi/hotspot2/pps/Credential.java13
-rw-r--r--wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java4
-rw-r--r--wifi/tests/src/android/net/wifi/FakeKeys.java29
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java192
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java23
492 files changed, 11817 insertions, 6424 deletions
diff --git a/Android.bp b/Android.bp
index 0780f88df7c6..e756b3428164 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1415,3 +1415,30 @@ filegroup {
name: "framework-telephony-jarjar-rules",
srcs: ["telephony/framework-telephony-jarjar-rules.txt"],
}
+
+// protolog start
+filegroup {
+ name: "protolog-common-src",
+ srcs: [
+ "core/java/com/android/internal/protolog/common/**/*.java",
+ ],
+}
+
+java_library {
+ name: "protolog-lib",
+ platform_apis: true,
+ srcs: [
+ "core/java/com/android/internal/protolog/ProtoLogImpl.java",
+ "core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java",
+ ":protolog-common-src",
+ ],
+}
+
+java_library {
+ name: "protolog-groups",
+ srcs: [
+ "core/java/com/android/internal/protolog/ProtoLogGroup.java",
+ ":protolog-common-src",
+ ],
+}
+// protolog end
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 0fe34fb650eb..2bd5aee0cd24 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -311,15 +311,6 @@ java_defaults {
compile_dex: true,
}
-java_defaults {
- name: "android_stubs_dists_default",
- dist: {
- targets: ["sdk", "win_sdk"],
- tag: ".jar",
- dest: "android.jar",
- },
-}
-
java_library_static {
name: "android_monolith_stubs_current",
srcs: [ ":api-stubs-docs" ],
@@ -355,21 +346,7 @@ java_library_static {
name: "android_system_monolith_stubs_current",
srcs: [ ":system-api-stubs-docs" ],
static_libs: [ "private-stub-annotations-jar" ],
- defaults: [
- "android_defaults_stubs_current",
- "android_stubs_dists_default",
- ],
- dist: {
- dir: "apistubs/android/system",
- },
- dists: [
- {
- // Legacy dist path
- targets: ["sdk", "win_sdk"],
- tag: ".jar",
- dest: "android_system.jar",
- },
- ],
+ defaults: ["android_defaults_stubs_current"],
}
java_library_static {
@@ -401,34 +378,14 @@ java_library_static {
name: "android_test_stubs_current",
srcs: [ ":test-api-stubs-docs" ],
static_libs: [ "private-stub-annotations-jar" ],
- defaults: [
- "android_defaults_stubs_current",
- "android_stubs_dists_default",
- ],
- dist: {
- dir: "apistubs/android/test",
- },
- dists: [
- {
- // Legacy dist path
- targets: ["sdk", "win_sdk"],
- tag: ".jar",
- dest: "android_test.jar",
- },
- ],
+ defaults: ["android_defaults_stubs_current"],
}
java_library_static {
name: "android_module_lib_stubs_current",
srcs: [ ":module-lib-api-stubs-docs-non-updatable" ],
- defaults: [
- "android_defaults_stubs_current",
- "android_stubs_dists_default",
- ],
+ defaults: ["android_defaults_stubs_current"],
libs: ["sdk_system_29_android"],
- dist: {
- dir: "apistubs/android/module-lib",
- },
}
java_library_static {
diff --git a/apct-tests/perftests/contentcapture/Android.bp b/apct-tests/perftests/contentcapture/Android.bp
index 66d7348008ab..19a66ad9f27b 100644
--- a/apct-tests/perftests/contentcapture/Android.bp
+++ b/apct-tests/perftests/contentcapture/Android.bp
@@ -20,9 +20,10 @@ android_test {
"androidx.test.rules",
"androidx.annotation_annotation",
"apct-perftests-utils",
- "collector-device-lib-platform",
+ "collector-device-lib",
"compatibility-device-util-axt",
],
platform_apis: true,
test_suites: ["device-tests"],
+ data: [":perfetto_artifacts"],
}
diff --git a/apct-tests/perftests/contentcapture/AndroidManifest.xml b/apct-tests/perftests/contentcapture/AndroidManifest.xml
index ee5577f265fa..80957c78abf3 100644
--- a/apct-tests/perftests/contentcapture/AndroidManifest.xml
+++ b/apct-tests/perftests/contentcapture/AndroidManifest.xml
@@ -16,11 +16,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.perftests.contentcapture">
- <uses-sdk android:targetSdkVersion="28" />
-
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.REAL_GET_TASKS" />
-
<application>
<uses-library android:name="android.test.runner" />
<activity android:name="android.view.contentcapture.CustomTestActivity"
diff --git a/apct-tests/perftests/contentcapture/AndroidTest.xml b/apct-tests/perftests/contentcapture/AndroidTest.xml
index d2386bb1efea..d8e0a17d3935 100644
--- a/apct-tests/perftests/contentcapture/AndroidTest.xml
+++ b/apct-tests/perftests/contentcapture/AndroidTest.xml
@@ -21,7 +21,39 @@
<option name="test-file-name" value="ContentCapturePerfTests.apk" />
</target_preparer>
+ <!-- Needed for pushing the trace config file -->
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="push-file" key="trace_config_detailed.textproto" value="/data/misc/perfetto-traces/trace_config.textproto" />
+ </target_preparer>
+
+ <!-- Needed for pulling the collected trace config on to the host -->
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="pull-pattern-keys" value="perfetto_file_path" />
+ </metrics_collector>
+
+ <!-- Needed for storing the perfetto trace files in the sdcard/test_results-->
+ <option name="isolated-storage" value="false" />
+
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.perftests.contentcapture" />
+
+ <!-- Listener related args for collecting the traces and waiting for the device to stabilize. -->
+ <option name="device-listeners" value="android.device.collectors.ProcLoadListener,android.device.collectors.PerfettoListener" />
+ <!-- Guarantee that user defined RunListeners will be running before any of the default listeners defined in this runner. -->
+ <option name="instrumentation-arg" key="newRunListenerMode" value="true" />
+
+ <!-- ProcLoadListener related arguments -->
+ <!-- Wait for device last minute threshold to reach 3 with 2 minute timeout before starting the test run -->
+ <option name="instrumentation-arg" key="procload-collector:per_run" value="true" />
+ <option name="instrumentation-arg" key="proc-loadavg-threshold" value="3" />
+ <option name="instrumentation-arg" key="proc-loadavg-timeout" value="120000" />
+ <option name="instrumentation-arg" key="proc-loadavg-interval" value="10000" />
+
+ <!-- PerfettoListener related arguments -->
+ <option name="instrumentation-arg" key="perfetto_config_text_proto" value="true" />
+ <option name="instrumentation-arg" key="perfetto_config_file" value="trace_config.textproto" />
+
+ <option name="instrumentation-arg" key="newRunListenerMode" value="true" />
</test>
</configuration>
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java b/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
index c276ae1fe45e..6e644ffb8b27 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
@@ -168,7 +168,9 @@ public final class SearchSpec {
/** Sets the maximum number of results to retrieve from the query */
@NonNull
public SearchSpec.Builder setNumToRetrieve(int numToRetrieve) {
- mResultSpecBuilder.setNumToRetrieve(numToRetrieve);
+ // Just retrieve everything in one page.
+ // TODO(b/152359656): Realign these two apis properly.
+ mResultSpecBuilder.setNumPerPage(numToRetrieve);
return this;
}
diff --git a/api/current.txt b/api/current.txt
index b70103b931d4..8cb5b0d68a19 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5596,6 +5596,7 @@ package android.app {
method public android.graphics.drawable.Icon getIcon();
method public android.app.RemoteInput[] getRemoteInputs();
method public int getSemanticAction();
+ method public boolean isAuthenticationRequired();
method public boolean isContextual();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.Notification.Action> CREATOR;
@@ -5625,6 +5626,7 @@ package android.app {
method @NonNull public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Extender);
method @NonNull public android.os.Bundle getExtras();
method @NonNull public android.app.Notification.Action.Builder setAllowGeneratedReplies(boolean);
+ method @NonNull public android.app.Notification.Action.Builder setAuthenticationRequired(boolean);
method @NonNull public android.app.Notification.Action.Builder setContextual(boolean);
method @NonNull public android.app.Notification.Action.Builder setSemanticAction(int);
}
@@ -24065,6 +24067,8 @@ package android.media {
method public boolean isSink();
method public boolean isSource();
field public static final int TYPE_AUX_LINE = 19; // 0x13
+ field public static final int TYPE_BLE_HEADSET = 26; // 0x1a
+ field public static final int TYPE_BLE_SPEAKER = 27; // 0x1b
field public static final int TYPE_BLUETOOTH_A2DP = 8; // 0x8
field public static final int TYPE_BLUETOOTH_SCO = 7; // 0x7
field public static final int TYPE_BUILTIN_EARPIECE = 1; // 0x1
@@ -65720,7 +65724,7 @@ package java.lang.reflect {
package java.math {
- public class BigDecimal extends java.lang.Number implements java.lang.Comparable<java.math.BigDecimal> java.io.Serializable {
+ public class BigDecimal extends java.lang.Number implements java.lang.Comparable<java.math.BigDecimal> {
ctor public BigDecimal(char[], int, int);
ctor public BigDecimal(char[], int, int, java.math.MathContext);
ctor public BigDecimal(char[]);
@@ -65807,19 +65811,20 @@ package java.math {
field public static final java.math.BigDecimal ZERO;
}
- public class BigInteger extends java.lang.Number implements java.lang.Comparable<java.math.BigInteger> java.io.Serializable {
+ public class BigInteger extends java.lang.Number implements java.lang.Comparable<java.math.BigInteger> {
+ ctor public BigInteger(byte[]);
+ ctor public BigInteger(int, byte[]);
+ ctor public BigInteger(@NonNull String, int);
+ ctor public BigInteger(@NonNull String);
ctor public BigInteger(int, @NonNull java.util.Random);
ctor public BigInteger(int, int, @NonNull java.util.Random);
- ctor public BigInteger(@NonNull String);
- ctor public BigInteger(@NonNull String, int);
- ctor public BigInteger(int, byte[]);
- ctor public BigInteger(byte[]);
method @NonNull public java.math.BigInteger abs();
method @NonNull public java.math.BigInteger add(@NonNull java.math.BigInteger);
method @NonNull public java.math.BigInteger and(@NonNull java.math.BigInteger);
method @NonNull public java.math.BigInteger andNot(@NonNull java.math.BigInteger);
method public int bitCount();
method public int bitLength();
+ method public byte byteValueExact();
method @NonNull public java.math.BigInteger clearBit(int);
method public int compareTo(@NonNull java.math.BigInteger);
method @NonNull public java.math.BigInteger divide(@NonNull java.math.BigInteger);
@@ -65830,8 +65835,10 @@ package java.math {
method @NonNull public java.math.BigInteger gcd(@NonNull java.math.BigInteger);
method public int getLowestSetBit();
method public int intValue();
+ method public int intValueExact();
method public boolean isProbablePrime(int);
method public long longValue();
+ method public long longValueExact();
method @NonNull public java.math.BigInteger max(@NonNull java.math.BigInteger);
method @NonNull public java.math.BigInteger min(@NonNull java.math.BigInteger);
method @NonNull public java.math.BigInteger mod(@NonNull java.math.BigInteger);
@@ -65848,6 +65855,7 @@ package java.math {
method @NonNull public java.math.BigInteger setBit(int);
method @NonNull public java.math.BigInteger shiftLeft(int);
method @NonNull public java.math.BigInteger shiftRight(int);
+ method public short shortValueExact();
method public int signum();
method @NonNull public java.math.BigInteger subtract(@NonNull java.math.BigInteger);
method public boolean testBit(int);
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index f53ac8c895ce..b587ea1f3b74 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -94,6 +94,7 @@ package android.os {
}
public interface Parcelable {
+ method public default int getStability();
field public static final int PARCELABLE_STABILITY_LOCAL = 0; // 0x0
field public static final int PARCELABLE_STABILITY_VINTF = 1; // 0x1
}
diff --git a/api/system-current.txt b/api/system-current.txt
index 1315a336213d..ea16238316ac 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -301,6 +301,7 @@ package android {
field public static final int config_helpIntentNameKey = 17039390; // 0x104001e
field public static final int config_helpPackageNameKey = 17039387; // 0x104001b
field public static final int config_helpPackageNameValue = 17039388; // 0x104001c
+ field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
field public static final int config_systemGallery = 17039399; // 0x1040027
}
@@ -7149,6 +7150,8 @@ package android.net.wifi {
field @Deprecated public static final int METERED_OVERRIDE_METERED = 1; // 0x1
field @Deprecated public static final int METERED_OVERRIDE_NONE = 0; // 0x0
field @Deprecated public static final int METERED_OVERRIDE_NOT_METERED = 2; // 0x2
+ field @Deprecated public static final int RANDOMIZATION_AUTO = 3; // 0x3
+ field @Deprecated public static final int RANDOMIZATION_ENHANCED = 2; // 0x2
field @Deprecated public static final int RANDOMIZATION_NONE = 0; // 0x0
field @Deprecated public static final int RANDOMIZATION_PERSISTENT = 1; // 0x1
field @Deprecated public static final int RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA = 17; // 0x11
diff --git a/api/test-current.txt b/api/test-current.txt
index 0ebbcd7fb3be..10a367fa9267 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -42,6 +42,7 @@ package android {
public static final class R.string {
field public static final int config_defaultAssistant = 17039393; // 0x1040021
field public static final int config_defaultDialer = 17039395; // 0x1040023
+ field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
field public static final int config_systemGallery = 17039399; // 0x1040027
}
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index a6c402ccc075..15e22a3410cf 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -166,7 +166,7 @@ Status Idmap2Service::verifyIdmap(const std::string& target_apk_path,
Status Idmap2Service::createIdmap(const std::string& target_apk_path,
const std::string& overlay_apk_path, int32_t fulfilled_policies,
bool enforce_overlayable, int32_t user_id ATTRIBUTE_UNUSED,
- aidl::nullable<std::string>* _aidl_return) {
+ std::optional<std::string>* _aidl_return) {
assert(_aidl_return);
SYSTRACE << "Idmap2Service::createIdmap " << target_apk_path << " " << overlay_apk_path;
_aidl_return->reset();
@@ -214,7 +214,7 @@ Status Idmap2Service::createIdmap(const std::string& target_apk_path,
return error("failed to write to idmap path " + idmap_path);
}
- *_aidl_return = aidl::make_nullable<std::string>(idmap_path);
+ *_aidl_return = idmap_path;
return ok();
}
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h
index ea931c936b0e..1a445192aff8 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.h
+++ b/cmds/idmap2/idmap2d/Idmap2Service.h
@@ -21,7 +21,6 @@
#include <android-base/unique_fd.h>
#include <binder/BinderService.h>
-#include <binder/Nullable.h>
#include "android/os/BnIdmap2.h"
@@ -47,7 +46,7 @@ class Idmap2Service : public BinderService<Idmap2Service>, public BnIdmap2 {
binder::Status createIdmap(const std::string& target_apk_path,
const std::string& overlay_apk_path, int32_t fulfilled_policies,
bool enforce_overlayable, int32_t user_id,
- aidl::nullable<std::string>* _aidl_return) override;
+ std::optional<std::string>* _aidl_return) override;
private:
// Cache the crc of the android framework package since the crc cannot change without a reboot.
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 1579715727ac..7c419519a558 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -85,8 +85,9 @@ cc_defaults {
"src/metrics/EventMetricProducer.cpp",
"src/metrics/GaugeMetricProducer.cpp",
"src/metrics/MetricProducer.cpp",
- "src/metrics/metrics_manager_util.cpp",
"src/metrics/MetricsManager.cpp",
+ "src/metrics/parsing_utils/config_update_utils.cpp",
+ "src/metrics/parsing_utils/metrics_manager_util.cpp",
"src/metrics/ValueMetricProducer.cpp",
"src/packages/UidMap.cpp",
"src/shell/shell_config.proto",
@@ -322,6 +323,8 @@ cc_test {
"tests/metrics/metrics_test_helper.cpp",
"tests/metrics/OringDurationTracker_test.cpp",
"tests/metrics/ValueMetricProducer_test.cpp",
+ "tests/metrics/parsing_utils/config_update_utils_test.cpp",
+ "tests/metrics/parsing_utils/metrics_manager_util_test.cpp",
"tests/MetricsManager_test.cpp",
"tests/shell/ShellSubscriber_test.cpp",
"tests/state/StateTracker_test.cpp",
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 6327490b0b71..7bee4e2d1a36 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -546,7 +546,8 @@ void StatsLogProcessor::OnConfigUpdatedLocked(const int64_t timestampNs, const C
}
} else {
// Preserve the existing MetricsManager, update necessary components and metadata in place.
- configValid = it->second->updateConfig(timestampNs, config);
+ configValid = it->second->updateConfig(config, mTimeBaseNs, timestampNs,
+ mAnomalyAlarmMonitor, mPeriodicAlarmMonitor);
if (configValid) {
// TODO(b/162323476): refresh TTL, ensure init() is handled properly.
mUidMap->OnConfigUpdated(key);
diff --git a/cmds/statsd/src/hash.h b/cmds/statsd/src/hash.h
index cfe869f60202..bd6b0cd47eaf 100644
--- a/cmds/statsd/src/hash.h
+++ b/cmds/statsd/src/hash.h
@@ -22,6 +22,7 @@ namespace android {
namespace os {
namespace statsd {
+// Uses murmur2 hashing algorithm.
extern uint32_t Hash32(const char *data, size_t n, uint32_t seed);
extern uint64_t Hash64(const char* data, size_t n, uint64_t seed);
diff --git a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp b/cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp
index b94a9572113e..60bcc26f0873 100644
--- a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp
+++ b/cmds/statsd/src/matchers/CombinationLogMatchingTracker.cpp
@@ -27,8 +27,9 @@ using std::set;
using std::unordered_map;
using std::vector;
-CombinationLogMatchingTracker::CombinationLogMatchingTracker(const int64_t& id, const int index)
- : LogMatchingTracker(id, index) {
+CombinationLogMatchingTracker::CombinationLogMatchingTracker(const int64_t& id, const int index,
+ const uint64_t protoHash)
+ : LogMatchingTracker(id, index, protoHash) {
}
CombinationLogMatchingTracker::~CombinationLogMatchingTracker() {
diff --git a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.h b/cmds/statsd/src/matchers/CombinationLogMatchingTracker.h
index 55bc46059fc1..6b8a7fb19cf0 100644
--- a/cmds/statsd/src/matchers/CombinationLogMatchingTracker.h
+++ b/cmds/statsd/src/matchers/CombinationLogMatchingTracker.h
@@ -28,7 +28,7 @@ namespace statsd {
// Represents a AtomMatcher_Combination in the StatsdConfig.
class CombinationLogMatchingTracker : public virtual LogMatchingTracker {
public:
- CombinationLogMatchingTracker(const int64_t& id, const int index);
+ CombinationLogMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash);
bool init(const std::vector<AtomMatcher>& allLogMatchers,
const std::vector<sp<LogMatchingTracker>>& allTrackers,
diff --git a/cmds/statsd/src/matchers/LogMatchingTracker.h b/cmds/statsd/src/matchers/LogMatchingTracker.h
index 88ab4e6f683a..49a41add4560 100644
--- a/cmds/statsd/src/matchers/LogMatchingTracker.h
+++ b/cmds/statsd/src/matchers/LogMatchingTracker.h
@@ -33,8 +33,8 @@ namespace statsd {
class LogMatchingTracker : public virtual RefBase {
public:
- LogMatchingTracker(const int64_t& id, const int index)
- : mId(id), mIndex(index), mInitialized(false){};
+ LogMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash)
+ : mId(id), mIndex(index), mInitialized(false), mProtoHash(protoHash){};
virtual ~LogMatchingTracker(){};
@@ -69,10 +69,14 @@ public:
return mAtomIds;
}
- const int64_t& getId() const {
+ int64_t getId() const {
return mId;
}
+ uint64_t getProtoHash() const {
+ return mProtoHash;
+ }
+
protected:
// Name of this matching. We don't really need the name, but it makes log message easy to debug.
const int64_t mId;
@@ -87,6 +91,14 @@ protected:
// return kNotMatched when we receive an event with an id not in the list. This is especially
// useful when we have a complex CombinationLogMatcherTracker.
std::set<int> mAtomIds;
+
+ // Hash of the AtomMatcher's proto bytes from StatsdConfig.
+ // Used to determine if the definition of this matcher has changed across a config update.
+ const uint64_t mProtoHash;
+
+ FRIEND_TEST(MetricsManagerTest, TestCreateLogTrackerSimple);
+ FRIEND_TEST(MetricsManagerTest, TestCreateLogTrackerCombination);
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateMatchers);
};
} // namespace statsd
diff --git a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp b/cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp
index 082daf5a1916..ff47d35b36cc 100644
--- a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp
+++ b/cmds/statsd/src/matchers/SimpleLogMatchingTracker.cpp
@@ -26,11 +26,11 @@ namespace statsd {
using std::unordered_map;
using std::vector;
-
SimpleLogMatchingTracker::SimpleLogMatchingTracker(const int64_t& id, const int index,
+ const uint64_t protoHash,
const SimpleAtomMatcher& matcher,
- const UidMap& uidMap)
- : LogMatchingTracker(id, index), mMatcher(matcher), mUidMap(uidMap) {
+ const sp<UidMap>& uidMap)
+ : LogMatchingTracker(id, index, protoHash), mMatcher(matcher), mUidMap(uidMap) {
if (!matcher.has_atom_id()) {
mInitialized = false;
} else {
diff --git a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.h b/cmds/statsd/src/matchers/SimpleLogMatchingTracker.h
index a0f6a888bd44..e58e01252ade 100644
--- a/cmds/statsd/src/matchers/SimpleLogMatchingTracker.h
+++ b/cmds/statsd/src/matchers/SimpleLogMatchingTracker.h
@@ -29,9 +29,8 @@ namespace statsd {
class SimpleLogMatchingTracker : public virtual LogMatchingTracker {
public:
- SimpleLogMatchingTracker(const int64_t& id, const int index,
- const SimpleAtomMatcher& matcher,
- const UidMap& uidMap);
+ SimpleLogMatchingTracker(const int64_t& id, const int index, const uint64_t protoHash,
+ const SimpleAtomMatcher& matcher, const sp<UidMap>& uidMap);
~SimpleLogMatchingTracker();
@@ -46,7 +45,7 @@ public:
private:
const SimpleAtomMatcher mMatcher;
- const UidMap& mUidMap;
+ const sp<UidMap> mUidMap;
};
} // namespace statsd
diff --git a/cmds/statsd/src/matchers/matcher_util.cpp b/cmds/statsd/src/matchers/matcher_util.cpp
index 2b4c6a3cbf1e..e6d91223308d 100644
--- a/cmds/statsd/src/matchers/matcher_util.cpp
+++ b/cmds/statsd/src/matchers/matcher_util.cpp
@@ -81,14 +81,15 @@ bool combinationMatch(const vector<int>& children, const LogicalOperation& opera
return matched;
}
-bool tryMatchString(const UidMap& uidMap, const FieldValue& fieldValue, const string& str_match) {
+bool tryMatchString(const sp<UidMap>& uidMap, const FieldValue& fieldValue,
+ const string& str_match) {
if (isAttributionUidField(fieldValue) || isUidField(fieldValue)) {
int uid = fieldValue.mValue.int_value;
auto aidIt = UidMap::sAidToUidMapping.find(str_match);
if (aidIt != UidMap::sAidToUidMapping.end()) {
return ((int)aidIt->second) == uid;
}
- std::set<string> packageNames = uidMap.getAppNamesFromUid(uid, true /* normalize*/);
+ std::set<string> packageNames = uidMap->getAppNamesFromUid(uid, true /* normalize*/);
return packageNames.find(str_match) != packageNames.end();
} else if (fieldValue.mValue.getType() == STRING) {
return fieldValue.mValue.str_value == str_match;
@@ -96,7 +97,7 @@ bool tryMatchString(const UidMap& uidMap, const FieldValue& fieldValue, const st
return false;
}
-bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
+bool matchesSimple(const sp<UidMap>& uidMap, const FieldValueMatcher& matcher,
const vector<FieldValue>& values, int start, int end, int depth) {
if (depth > 2) {
ALOGE("Depth > 3 not supported");
@@ -353,7 +354,7 @@ bool matchesSimple(const UidMap& uidMap, const FieldValueMatcher& matcher,
}
}
-bool matchesSimple(const UidMap& uidMap, const SimpleAtomMatcher& simpleMatcher,
+bool matchesSimple(const sp<UidMap>& uidMap, const SimpleAtomMatcher& simpleMatcher,
const LogEvent& event) {
if (event.GetTagId() != simpleMatcher.atom_id()) {
return false;
diff --git a/cmds/statsd/src/matchers/matcher_util.h b/cmds/statsd/src/matchers/matcher_util.h
index 1ab3e87b5fed..130b6068bd19 100644
--- a/cmds/statsd/src/matchers/matcher_util.h
+++ b/cmds/statsd/src/matchers/matcher_util.h
@@ -36,8 +36,8 @@ enum MatchingState {
bool combinationMatch(const std::vector<int>& children, const LogicalOperation& operation,
const std::vector<MatchingState>& matcherResults);
-bool matchesSimple(const UidMap& uidMap,
- const SimpleAtomMatcher& simpleMatcher, const LogEvent& wrapper);
+bool matchesSimple(const sp<UidMap>& uidMap, const SimpleAtomMatcher& simpleMatcher,
+ const LogEvent& wrapper);
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 189d8117ae55..2c3deca40fa0 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -26,7 +26,8 @@
#include "guardrail/StatsdStats.h"
#include "matchers/CombinationLogMatchingTracker.h"
#include "matchers/SimpleLogMatchingTracker.h"
-#include "metrics_manager_util.h"
+#include "parsing_utils/config_update_utils.h"
+#include "parsing_utils/metrics_manager_util.h"
#include "state/StateManager.h"
#include "stats_log_util.h"
#include "stats_util.h"
@@ -76,13 +77,14 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
// Init the ttl end timestamp.
refreshTtl(timeBaseNs);
- mConfigValid = initStatsdConfig(
- key, config, *uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseNs, currentTimeNs, mTagIds, mAllAtomMatchers, mAllConditionTrackers,
- mAllMetricProducers, mAllAnomalyTrackers, mAllPeriodicAlarmTrackers,
- mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap,
- mActivationAtomTrackerToMetricMap, mDeactivationAtomTrackerToMetricMap,
- mAlertTrackerMap, mMetricIndexesWithActivation, mNoReportMetricIds);
+ mConfigValid =
+ initStatsdConfig(key, config, uidMap, pullerManager, anomalyAlarmMonitor,
+ periodicAlarmMonitor, timeBaseNs, currentTimeNs, mTagIds,
+ mAllAtomMatchers, mLogTrackerMap, mAllConditionTrackers,
+ mAllMetricProducers, mAllAnomalyTrackers, mAllPeriodicAlarmTrackers,
+ mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap,
+ mActivationAtomTrackerToMetricMap, mDeactivationAtomTrackerToMetricMap,
+ mAlertTrackerMap, mMetricIndexesWithActivation, mNoReportMetricIds);
mHashStringsInReport = config.hash_strings_in_metric_report();
mVersionStringsInReport = config.version_strings_in_metric_report();
@@ -195,7 +197,19 @@ MetricsManager::~MetricsManager() {
VLOG("~MetricsManager()");
}
-bool MetricsManager::updateConfig(const int64_t currentTimeNs, const StatsdConfig& config) {
+bool MetricsManager::updateConfig(const StatsdConfig& config, const int64_t timeBaseNs,
+ const int64_t currentTimeNs,
+ const sp<AlarmMonitor>& anomalyAlarmMonitor,
+ const sp<AlarmMonitor>& periodicAlarmMonitor) {
+ vector<sp<LogMatchingTracker>> newAtomMatchers;
+ unordered_map<int64_t, int> newLogTrackerMap;
+ mTagIds.clear();
+ mConfigValid =
+ updateStatsdConfig(mConfigKey, config, mUidMap, mPullerManager, anomalyAlarmMonitor,
+ periodicAlarmMonitor, timeBaseNs, currentTimeNs, mAllAtomMatchers,
+ mLogTrackerMap, mTagIds, newAtomMatchers, newLogTrackerMap);
+ mAllAtomMatchers = newAtomMatchers;
+ mLogTrackerMap = newLogTrackerMap;
return mConfigValid;
}
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index 042de29e173d..6f9a23362033 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -46,7 +46,9 @@ public:
virtual ~MetricsManager();
- bool updateConfig(const int64_t currentTimeNs, const StatsdConfig& config);
+ bool updateConfig(const StatsdConfig& config, const int64_t timeBaseNs,
+ const int64_t currentTimeNs, const sp<AlarmMonitor>& anomalyAlarmMonitor,
+ const sp<AlarmMonitor>& periodicAlarmMonitor);
// Return whether the configuration is valid.
bool isConfigValid() const;
@@ -237,6 +239,12 @@ private:
// Hold all periodic alarm trackers.
std::vector<sp<AlarmTracker>> mAllPeriodicAlarmTrackers;
+ // To make updating configs faster, we map the id of a LogMatchingTracker, MetricProducer, and
+ // ConditionTracker to its index in the corresponding vector.
+
+ // Maps the id of an atom matcher to its index in mAllAtomMatchers.
+ std::unordered_map<int64_t, int> mLogTrackerMap;
+
// To make the log processing more efficient, we want to do as much filtering as possible
// before we go into individual trackers and conditions to match.
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
new file mode 100644
index 000000000000..562e29124187
--- /dev/null
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#define DEBUG false // STOPSHIP if true
+
+#include "config_update_utils.h"
+
+#include "external/StatsPullerManager.h"
+#include "hash.h"
+#include "metrics_manager_util.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+// Recursive function to determine if a matcher needs to be updated. Populates matcherToUpdate.
+// Returns whether the function was successful or not.
+bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherIdx,
+ const unordered_map<int64_t, int>& oldLogTrackerMap,
+ const vector<sp<LogMatchingTracker>>& oldAtomMatchers,
+ const unordered_map<int64_t, int>& newLogTrackerMap,
+ vector<UpdateStatus>& matchersToUpdate,
+ vector<bool>& cycleTracker) {
+ // Have already examined this matcher.
+ if (matchersToUpdate[matcherIdx] != UPDATE_UNKNOWN) {
+ return true;
+ }
+
+ const AtomMatcher& matcher = config.atom_matcher(matcherIdx);
+ int64_t id = matcher.id();
+ // Check if new matcher.
+ const auto& oldLogTrackerIt = oldLogTrackerMap.find(id);
+ if (oldLogTrackerIt == oldLogTrackerMap.end()) {
+ matchersToUpdate[matcherIdx] = UPDATE_REPLACE;
+ return true;
+ }
+
+ // This is an existing matcher. Check if it has changed.
+ string serializedMatcher;
+ if (!matcher.SerializeToString(&serializedMatcher)) {
+ ALOGE("Unable to serialize matcher %lld", (long long)id);
+ return false;
+ }
+ uint64_t newProtoHash = Hash64(serializedMatcher);
+ if (newProtoHash != oldAtomMatchers[oldLogTrackerIt->second]->getProtoHash()) {
+ matchersToUpdate[matcherIdx] = UPDATE_REPLACE;
+ return true;
+ }
+
+ switch (matcher.contents_case()) {
+ case AtomMatcher::ContentsCase::kSimpleAtomMatcher: {
+ matchersToUpdate[matcherIdx] = UPDATE_PRESERVE;
+ return true;
+ }
+ case AtomMatcher::ContentsCase::kCombination: {
+ // Recurse to check if children have changed.
+ cycleTracker[matcherIdx] = true;
+ UpdateStatus status = UPDATE_PRESERVE;
+ for (const int64_t childMatcherId : matcher.combination().matcher()) {
+ const auto& childIt = newLogTrackerMap.find(childMatcherId);
+ if (childIt == newLogTrackerMap.end()) {
+ ALOGW("Matcher %lld not found in the config", (long long)childMatcherId);
+ return false;
+ }
+ const int childIdx = childIt->second;
+ if (cycleTracker[childIdx]) {
+ ALOGE("Cycle detected in matcher config");
+ return false;
+ }
+ if (!determineMatcherUpdateStatus(config, childIdx, oldLogTrackerMap,
+ oldAtomMatchers, newLogTrackerMap,
+ matchersToUpdate, cycleTracker)) {
+ return false;
+ }
+
+ if (matchersToUpdate[childIdx] == UPDATE_REPLACE) {
+ status = UPDATE_REPLACE;
+ break;
+ }
+ }
+ matchersToUpdate[matcherIdx] = status;
+ cycleTracker[matcherIdx] = false;
+ return true;
+ }
+ default: {
+ ALOGE("Matcher \"%lld\" malformed", (long long)id);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool updateLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
+ const unordered_map<int64_t, int>& oldLogTrackerMap,
+ const vector<sp<LogMatchingTracker>>& oldAtomMatchers, set<int>& allTagIds,
+ unordered_map<int64_t, int>& newLogTrackerMap,
+ vector<sp<LogMatchingTracker>>& newAtomMatchers) {
+ const int atomMatcherCount = config.atom_matcher_size();
+
+ vector<AtomMatcher> matcherProtos;
+ matcherProtos.reserve(atomMatcherCount);
+ newAtomMatchers.reserve(atomMatcherCount);
+
+ // Maps matcher id to their position in the config. For fast lookup of dependencies.
+ for (int i = 0; i < atomMatcherCount; i++) {
+ const AtomMatcher& matcher = config.atom_matcher(i);
+ if (newLogTrackerMap.find(matcher.id()) != newLogTrackerMap.end()) {
+ ALOGE("Duplicate atom matcher found for id %lld", (long long)matcher.id());
+ return false;
+ }
+ newLogTrackerMap[matcher.id()] = i;
+ matcherProtos.push_back(matcher);
+ }
+
+ // For combination matchers, we need to determine if any children need to be updated.
+ vector<UpdateStatus> matchersToUpdate(atomMatcherCount, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(atomMatcherCount, false);
+ for (int i = 0; i < atomMatcherCount; i++) {
+ if (!determineMatcherUpdateStatus(config, i, oldLogTrackerMap, oldAtomMatchers,
+ newLogTrackerMap, matchersToUpdate, cycleTracker)) {
+ return false;
+ }
+ }
+
+ for (int i = 0; i < atomMatcherCount; i++) {
+ const AtomMatcher& matcher = config.atom_matcher(i);
+ const int64_t id = matcher.id();
+ switch (matchersToUpdate[i]) {
+ case UPDATE_PRESERVE: {
+ const auto& oldLogTrackerIt = oldLogTrackerMap.find(id);
+ if (oldLogTrackerIt == oldLogTrackerMap.end()) {
+ ALOGE("Could not find AtomMatcher %lld in the previous config, but expected it "
+ "to be there",
+ (long long)id);
+ return false;
+ }
+ const int oldIndex = oldLogTrackerIt->second;
+ newAtomMatchers.push_back(oldAtomMatchers[oldIndex]);
+ break;
+ }
+ case UPDATE_REPLACE: {
+ sp<LogMatchingTracker> tracker = createLogTracker(matcher, i, uidMap);
+ if (tracker == nullptr) {
+ return false;
+ }
+ newAtomMatchers.push_back(tracker);
+ break;
+ }
+ default: {
+ ALOGE("Matcher \"%lld\" update state is unknown. This should never happen",
+ (long long)id);
+ return false;
+ }
+ }
+ }
+
+ std::fill(cycleTracker.begin(), cycleTracker.end(), false);
+ for (auto& matcher : newAtomMatchers) {
+ if (!matcher->init(matcherProtos, newAtomMatchers, newLogTrackerMap, cycleTracker)) {
+ return false;
+ }
+ // Collect all the tag ids that are interesting. TagIds exist in leaf nodes only.
+ const set<int>& tagIds = matcher->getAtomIds();
+ allTagIds.insert(tagIds.begin(), tagIds.end());
+ }
+
+ return true;
+}
+
+bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
+ const sp<StatsPullerManager>& pullerManager,
+ const sp<AlarmMonitor>& anomalyAlarmMonitor,
+ const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
+ const int64_t currentTimeNs,
+ const vector<sp<LogMatchingTracker>>& oldAtomMatchers,
+ const unordered_map<int64_t, int>& oldLogTrackerMap, set<int>& allTagIds,
+ vector<sp<LogMatchingTracker>>& newAtomMatchers,
+ unordered_map<int64_t, int>& newLogTrackerMap) {
+ if (!updateLogTrackers(config, uidMap, oldLogTrackerMap, oldAtomMatchers, allTagIds,
+ newLogTrackerMap, newAtomMatchers)) {
+ ALOGE("updateLogMatchingTrackers failed");
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android \ No newline at end of file
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
new file mode 100644
index 000000000000..951ab03cee47
--- /dev/null
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include "anomaly/AlarmMonitor.h"
+#include "external/StatsPullerManager.h"
+#include "matchers/LogMatchingTracker.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+// Helper functions for MetricsManager to update itself from a new StatsdConfig.
+// *Note*: only updateStatsdConfig() should be called from outside this file.
+// All other functions are intermediate steps, created to make unit testing easier.
+
+// Possible update states for a component. PRESERVE means we should keep the existing one.
+// REPLACE means we should create a new one, either because it didn't exist or it changed.
+enum UpdateStatus {
+ UPDATE_UNKNOWN = 0,
+ UPDATE_PRESERVE = 1,
+ UPDATE_REPLACE = 2,
+};
+
+// Recursive function to determine if a matcher needs to be updated.
+// input:
+// [config]: the input StatsdConfig
+// [matcherIdx]: the index of the current matcher to be updated
+// [newLogTrackerMap]: matcher id to index mapping in the input StatsdConfig
+// [oldLogTrackerMap]: matcher id to index mapping in the existing MetricsManager
+// [oldAtomMatchers]: stores the existing LogMatchingTrackers
+// output:
+// [matchersToUpdate]: vector of the update status of each matcher. The matcherIdx index will
+// be updated from UPDATE_UNKNOWN after this call.
+// [cycleTracker]: intermediate param used during recursion.
+bool determineMatcherUpdateStatus(const StatsdConfig& config, const int matcherIdx,
+ const unordered_map<int64_t, int>& oldLogTrackerMap,
+ const vector<sp<LogMatchingTracker>>& oldAtomMatchers,
+ const unordered_map<int64_t, int>& newLogTrackerMap,
+ vector<UpdateStatus>& matchersToUpdate,
+ vector<bool>& cycleTracker);
+
+// Updates the LogMatchingTrackers.
+// input:
+// [config]: the input StatsdConfig
+// [oldLogTrackerMap]: existing matcher id to index mapping
+// [oldAtomMatchers]: stores the existing LogMatchingTrackers
+// output:
+// [allTagIds]: contains the set of all interesting tag ids to this config.
+// [newLogTrackerMap]: new matcher id to index mapping
+// [newAtomMatchers]: stores the new LogMatchingTrackers
+bool updateLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
+ const unordered_map<int64_t, int>& oldLogTrackerMap,
+ const vector<sp<LogMatchingTracker>>& oldAtomMatchers, set<int>& allTagIds,
+ unordered_map<int64_t, int>& newLogTrackerMap,
+ vector<sp<LogMatchingTracker>>& newAtomMatchers);
+
+// Updates the existing MetricsManager from a new StatsdConfig.
+// Parameters are the members of MetricsManager. See MetricsManager for declaration.
+bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
+ const sp<StatsPullerManager>& pullerManager,
+ const sp<AlarmMonitor>& anomalyAlarmMonitor,
+ const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
+ const int64_t currentTimeNs,
+ const std::vector<sp<LogMatchingTracker>>& oldAtomMatchers,
+ const unordered_map<int64_t, int>& oldLogTrackerMap,
+ std::set<int>& allTagIds,
+ std::vector<sp<LogMatchingTracker>>& newAtomMatchers,
+ unordered_map<int64_t, int>& newLogTrackerMap);
+
+} // namespace statsd
+} // namespace os
+} // namespace android \ No newline at end of file
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.cpp b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
index 8917c36bb608..9d3943fe8260 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
@@ -22,10 +22,10 @@
#include <inttypes.h>
#include "FieldValue.h"
-#include "MetricProducer.h"
#include "condition/CombinationConditionTracker.h"
#include "condition/SimpleConditionTracker.h"
#include "external/StatsPullerManager.h"
+#include "hash.h"
#include "matchers/CombinationLogMatchingTracker.h"
#include "matchers/EventMatcherWizard.h"
#include "matchers/SimpleLogMatchingTracker.h"
@@ -33,6 +33,7 @@
#include "metrics/DurationMetricProducer.h"
#include "metrics/EventMetricProducer.h"
#include "metrics/GaugeMetricProducer.h"
+#include "metrics/MetricProducer.h"
#include "metrics/ValueMetricProducer.h"
#include "state/StateManager.h"
#include "stats_util.h"
@@ -61,6 +62,28 @@ bool hasLeafNode(const FieldMatcher& matcher) {
} // namespace
+sp<LogMatchingTracker> createLogTracker(const AtomMatcher& logMatcher, const int index,
+ const sp<UidMap>& uidMap) {
+ string serializedMatcher;
+ if (!logMatcher.SerializeToString(&serializedMatcher)) {
+ ALOGE("Unable to serialize matcher %lld", (long long)logMatcher.id());
+ return nullptr;
+ }
+ uint64_t protoHash = Hash64(serializedMatcher);
+ switch (logMatcher.contents_case()) {
+ case AtomMatcher::ContentsCase::kSimpleAtomMatcher:
+ return new SimpleLogMatchingTracker(logMatcher.id(), index, protoHash,
+ logMatcher.simple_atom_matcher(), uidMap);
+ break;
+ case AtomMatcher::ContentsCase::kCombination:
+ return new CombinationLogMatchingTracker(logMatcher.id(), index, protoHash);
+ break;
+ default:
+ ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id());
+ return nullptr;
+ }
+}
+
bool handleMetricWithLogTrackers(const int64_t what, const int metricIndex,
const bool usedForDimension,
const vector<sp<LogMatchingTracker>>& allAtomMatchers,
@@ -125,8 +148,6 @@ bool handleMetricWithConditions(
ALOGW("cannot find Predicate \"%lld\" in the config", (long long)link.condition());
return false;
}
- allConditionTrackers[condition_it->second]->setSliced(true);
- allConditionTrackers[it->second]->setSliced(true);
}
conditionIndex = condition_it->second;
@@ -184,9 +205,7 @@ bool handleMetricWithStateLink(const FieldMatcher& stateMatcher,
// to provide the producer with state about its activators and deactivators.
// Returns false if there are errors.
bool handleMetricActivation(
- const StatsdConfig& config,
- const int64_t metricId,
- const int metricIndex,
+ const StatsdConfig& config, const int64_t metricId, const int metricIndex,
const unordered_map<int64_t, int>& metricToActivationMap,
const unordered_map<int64_t, int>& logTrackerMap,
unordered_map<int, vector<int>>& activationAtomTrackerToMetricMap,
@@ -210,10 +229,11 @@ bool handleMetricActivation(
return false;
}
- ActivationType activationType = (activation.has_activation_type()) ?
- activation.activation_type() : metricActivation.activation_type();
- std::shared_ptr<Activation> activationWrapper = std::make_shared<Activation>(
- activationType, activation.ttl_seconds() * NS_PER_SEC);
+ ActivationType activationType = (activation.has_activation_type())
+ ? activation.activation_type()
+ : metricActivation.activation_type();
+ std::shared_ptr<Activation> activationWrapper =
+ std::make_shared<Activation>(activationType, activation.ttl_seconds() * NS_PER_SEC);
int atomMatcherIndex = itr->second;
activationAtomTrackerToMetricMap[atomMatcherIndex].push_back(metricIndex);
@@ -235,7 +255,7 @@ bool handleMetricActivation(
return true;
}
-bool initLogTrackers(const StatsdConfig& config, const UidMap& uidMap,
+bool initLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
unordered_map<int64_t, int>& logTrackerMap,
vector<sp<LogMatchingTracker>>& allAtomMatchers, set<int>& allTagIds) {
vector<AtomMatcher> matcherConfigs;
@@ -245,22 +265,12 @@ bool initLogTrackers(const StatsdConfig& config, const UidMap& uidMap,
for (int i = 0; i < atomMatcherCount; i++) {
const AtomMatcher& logMatcher = config.atom_matcher(i);
-
int index = allAtomMatchers.size();
- switch (logMatcher.contents_case()) {
- case AtomMatcher::ContentsCase::kSimpleAtomMatcher:
- allAtomMatchers.push_back(new SimpleLogMatchingTracker(
- logMatcher.id(), index, logMatcher.simple_atom_matcher(), uidMap));
- break;
- case AtomMatcher::ContentsCase::kCombination:
- allAtomMatchers.push_back(
- new CombinationLogMatchingTracker(logMatcher.id(), index));
- break;
- default:
- ALOGE("Matcher \"%lld\" malformed", (long long)logMatcher.id());
- return false;
- // continue;
+ sp<LogMatchingTracker> tracker = createLogTracker(logMatcher, index, uidMap);
+ if (tracker == nullptr) {
+ return false;
}
+ allAtomMatchers.push_back(tracker);
if (logTrackerMap.find(logMatcher.id()) != logTrackerMap.end()) {
ALOGE("Duplicate AtomMatcher found!");
return false;
@@ -383,7 +393,7 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
const MetricActivation& metricActivation = config.metric_activation(i);
int64_t metricId = metricActivation.metric_id();
if (metricToActivationMap.find(metricId) != metricToActivationMap.end()) {
- ALOGE("Metric %lld has multiple MetricActivations", (long long) metricId);
+ ALOGE("Metric %lld has multiple MetricActivations", (long long)metricId);
return false;
}
metricToActivationMap.insert({metricId, i});
@@ -402,9 +412,8 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
metricMap.insert({metric.id(), metricIndex});
int trackerIndex;
if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchers, logTrackerMap, trackerToMetricMap,
- trackerIndex)) {
+ metric.has_dimensions_in_what(), allAtomMatchers,
+ logTrackerMap, trackerToMetricMap, trackerIndex)) {
return false;
}
@@ -438,10 +447,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- bool success = handleMetricActivation(config, metric.id(), metricIndex,
- metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
- eventDeactivationMap);
+ bool success = handleMetricActivation(
+ config, metric.id(), metricIndex, metricToActivationMap, logTrackerMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap);
if (!success) return false;
sp<MetricProducer> countProducer =
@@ -544,10 +553,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- bool success = handleMetricActivation(config, metric.id(), metricIndex,
- metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
- eventDeactivationMap);
+ bool success = handleMetricActivation(
+ config, metric.id(), metricIndex, metricToActivationMap, logTrackerMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap);
if (!success) return false;
sp<MetricProducer> durationMetric = new DurationMetricProducer(
@@ -591,10 +600,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- bool success = handleMetricActivation(config, metric.id(), metricIndex,
- metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
- eventDeactivationMap);
+ bool success = handleMetricActivation(
+ config, metric.id(), metricIndex, metricToActivationMap, logTrackerMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap);
if (!success) return false;
sp<MetricProducer> eventMetric =
@@ -626,9 +635,8 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
metricMap.insert({metric.id(), metricIndex});
int trackerIndex;
if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchers, logTrackerMap, trackerToMetricMap,
- trackerIndex)) {
+ metric.has_dimensions_in_what(), allAtomMatchers,
+ logTrackerMap, trackerToMetricMap, trackerIndex)) {
return false;
}
@@ -718,9 +726,8 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
metricMap.insert({metric.id(), metricIndex});
int trackerIndex;
if (!handleMetricWithLogTrackers(metric.what(), metricIndex,
- metric.has_dimensions_in_what(),
- allAtomMatchers, logTrackerMap, trackerToMetricMap,
- trackerIndex)) {
+ metric.has_dimensions_in_what(), allAtomMatchers,
+ logTrackerMap, trackerToMetricMap, trackerIndex)) {
return false;
}
@@ -775,10 +782,10 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
unordered_map<int, shared_ptr<Activation>> eventActivationMap;
unordered_map<int, vector<shared_ptr<Activation>>> eventDeactivationMap;
- bool success = handleMetricActivation(config, metric.id(), metricIndex,
- metricToActivationMap, logTrackerMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, metricsWithActivation, eventActivationMap,
- eventDeactivationMap);
+ bool success = handleMetricActivation(
+ config, metric.id(), metricIndex, metricToActivationMap, logTrackerMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, eventActivationMap, eventDeactivationMap);
if (!success) return false;
sp<MetricProducer> gaugeProducer = new GaugeMetricProducer(
@@ -813,8 +820,7 @@ bool initMetrics(const ConfigKey& key, const StatsdConfig& config, const int64_t
return true;
}
-bool initAlerts(const StatsdConfig& config,
- const unordered_map<int64_t, int>& metricProducerMap,
+bool initAlerts(const StatsdConfig& config, const unordered_map<int64_t, int>& metricProducerMap,
unordered_map<int64_t, int>& alertTrackerMap,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
vector<sp<MetricProducer>>& allMetricProducers,
@@ -832,8 +838,8 @@ bool initAlerts(const StatsdConfig& config,
return false;
}
if (alert.trigger_if_sum_gt() < 0 || alert.num_buckets() <= 0) {
- ALOGW("invalid alert: threshold=%f num_buckets= %d",
- alert.trigger_if_sum_gt(), alert.num_buckets());
+ ALOGW("invalid alert: threshold=%f num_buckets= %d", alert.trigger_if_sum_gt(),
+ alert.num_buckets());
return false;
}
const int metricIndex = itr->second;
@@ -853,14 +859,13 @@ bool initAlerts(const StatsdConfig& config,
}
if (subscription.subscriber_information_case() ==
Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
- ALOGW("subscription \"%lld\" has no subscriber info.\"",
- (long long)subscription.id());
+ ALOGW("subscription \"%lld\" has no subscriber info.\"", (long long)subscription.id());
return false;
}
const auto& itr = alertTrackerMap.find(subscription.rule_id());
if (itr == alertTrackerMap.end()) {
ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
- (long long)subscription.id(), (long long)subscription.rule_id());
+ (long long)subscription.id(), (long long)subscription.rule_id());
return false;
}
const int anomalyTrackerIndex = itr->second;
@@ -870,12 +875,11 @@ bool initAlerts(const StatsdConfig& config,
}
bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
- const sp<AlarmMonitor>& periodicAlarmMonitor,
- const int64_t timeBaseNs, const int64_t currentTimeNs,
- vector<sp<AlarmTracker>>& allAlarmTrackers) {
+ const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
+ const int64_t currentTimeNs, vector<sp<AlarmTracker>>& allAlarmTrackers) {
unordered_map<int64_t, int> alarmTrackerMap;
int64_t startMillis = timeBaseNs / 1000 / 1000;
- int64_t currentTimeMillis = currentTimeNs / 1000 /1000;
+ int64_t currentTimeMillis = currentTimeNs / 1000 / 1000;
for (int i = 0; i < config.alarm_size(); i++) {
const Alarm& alarm = config.alarm(i);
if (alarm.offset_millis() <= 0) {
@@ -888,8 +892,7 @@ bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
}
alarmTrackerMap.insert(std::make_pair(alarm.id(), allAlarmTrackers.size()));
allAlarmTrackers.push_back(
- new AlarmTracker(startMillis, currentTimeMillis,
- alarm, key, periodicAlarmMonitor));
+ new AlarmTracker(startMillis, currentTimeMillis, alarm, key, periodicAlarmMonitor));
}
for (int i = 0; i < config.subscription_size(); ++i) {
const Subscription& subscription = config.subscription(i);
@@ -898,14 +901,13 @@ bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
}
if (subscription.subscriber_information_case() ==
Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
- ALOGW("subscription \"%lld\" has no subscriber info.\"",
- (long long)subscription.id());
+ ALOGW("subscription \"%lld\" has no subscriber info.\"", (long long)subscription.id());
return false;
}
const auto& itr = alarmTrackerMap.find(subscription.rule_id());
if (itr == alarmTrackerMap.end()) {
ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
- (long long)subscription.id(), (long long)subscription.rule_id());
+ (long long)subscription.id(), (long long)subscription.rule_id());
return false;
}
const int trackerIndex = itr->second;
@@ -914,12 +916,13 @@ bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
return true;
}
-bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
+bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
const sp<StatsPullerManager>& pullerManager,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
const int64_t currentTimeNs, set<int>& allTagIds,
vector<sp<LogMatchingTracker>>& allAtomMatchers,
+ unordered_map<int64_t, int>& logTrackerMap,
vector<sp<ConditionTracker>>& allConditionTrackers,
vector<sp<MetricProducer>>& allMetricProducers,
vector<sp<AnomalyTracker>>& allAnomalyTrackers,
@@ -930,9 +933,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap&
unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
unordered_map<int64_t, int>& alertTrackerMap,
- vector<int>& metricsWithActivation,
- std::set<int64_t>& noReportMetricIds) {
- unordered_map<int64_t, int> logTrackerMap;
+ vector<int>& metricsWithActivation, std::set<int64_t>& noReportMetricIds) {
unordered_map<int64_t, int> conditionTrackerMap;
vector<ConditionState> initialConditionCache;
unordered_map<int64_t, int> metricProducerMap;
@@ -969,8 +970,8 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap&
ALOGE("initAlerts failed");
return false;
}
- if (!initAlarms(config, key, periodicAlarmMonitor,
- timeBaseNs, currentTimeNs, allPeriodicAlarmTrackers)) {
+ if (!initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
+ allPeriodicAlarmTrackers)) {
ALOGE("initAlarms failed");
return false;
}
diff --git a/cmds/statsd/src/metrics/metrics_manager_util.h b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
index 96b5c26ff789..ed9951fd5ee6 100644
--- a/cmds/statsd/src/metrics/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
@@ -20,16 +20,28 @@
#include <unordered_map>
#include <vector>
-#include "../anomaly/AlarmTracker.h"
-#include "../condition/ConditionTracker.h"
-#include "../external/StatsPullerManager.h"
-#include "../matchers/LogMatchingTracker.h"
-#include "../metrics/MetricProducer.h"
+#include "anomaly/AlarmTracker.h"
+#include "condition/ConditionTracker.h"
+#include "external/StatsPullerManager.h"
+#include "matchers/LogMatchingTracker.h"
+#include "metrics/MetricProducer.h"
namespace android {
namespace os {
namespace statsd {
+// Helper functions for creating individual config components from StatsdConfig.
+// Should only be called from metrics_manager_util and config_update_utils.
+
+// Create a LogMatchingTracker.
+// input:
+// [logMatcher]: the input AtomMatcher from the StatsdConfig
+// [index]: the index of the matcher
+// output:
+// new LogMatchingTracker, or null if the tracker is unable to be created
+sp<LogMatchingTracker> createLogTracker(const AtomMatcher& logMatcher, const int index,
+ const sp<UidMap>& uidMap);
+
// Helper functions for MetricsManager to initialize from StatsdConfig.
// *Note*: only initStatsdConfig() should be called from outside.
// All other functions are intermediate
@@ -44,8 +56,7 @@ namespace statsd {
// [logTrackerMap]: this map should contain matcher name to index mapping
// [allAtomMatchers]: should store the sp to all the LogMatchingTracker
// [allTagIds]: contains the set of all interesting tag ids to this config.
-bool initLogTrackers(const StatsdConfig& config,
- const UidMap& uidMap,
+bool initLogTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
std::unordered_map<int64_t, int>& logTrackerMap,
std::vector<sp<LogMatchingTracker>>& allAtomMatchers,
std::set<int>& allTagIds);
@@ -97,7 +108,7 @@ bool initStates(const StatsdConfig& config, unordered_map<int64_t, int>& stateAt
// [trackerToMetricMap]: contains the mapping from log tracker to MetricProducer index.
bool initMetrics(
const ConfigKey& key, const StatsdConfig& config, const int64_t timeBaseTimeNs,
- const int64_t currentTimeNs, UidMap& uidMap, const sp<StatsPullerManager>& pullerManager,
+ const int64_t currentTimeNs, const sp<StatsPullerManager>& pullerManager,
const std::unordered_map<int64_t, int>& logTrackerMap,
const std::unordered_map<int64_t, int>& conditionTrackerMap,
const std::unordered_map<int, std::vector<MetricConditionLink>>& eventConditionLinks,
@@ -116,12 +127,13 @@ bool initMetrics(
// Initialize MetricsManager from StatsdConfig.
// Parameters are the members of MetricsManager. See MetricsManager for declaration.
-bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap& uidMap,
+bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
const sp<StatsPullerManager>& pullerManager,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
const int64_t currentTimeNs, std::set<int>& allTagIds,
std::vector<sp<LogMatchingTracker>>& allAtomMatchers,
+ std::unordered_map<int64_t, int>& logTrackerMap,
std::vector<sp<ConditionTracker>>& allConditionTrackers,
std::vector<sp<MetricProducer>>& allMetricProducers,
vector<sp<AnomalyTracker>>& allAnomalyTrackers,
@@ -132,8 +144,7 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, UidMap&
unordered_map<int, std::vector<int>>& activationAtomTrackerToMetricMap,
unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
std::unordered_map<int64_t, int>& alertTrackerMap,
- vector<int>& metricsWithActivation,
- std::set<int64_t>& noReportMetricIds);
+ vector<int>& metricsWithActivation, std::set<int64_t>& noReportMetricIds);
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/src/shell/ShellSubscriber.cpp b/cmds/statsd/src/shell/ShellSubscriber.cpp
index fd883c29dba0..9d8f0c24e253 100644
--- a/cmds/statsd/src/shell/ShellSubscriber.cpp
+++ b/cmds/statsd/src/shell/ShellSubscriber.cpp
@@ -191,7 +191,7 @@ void ShellSubscriber::writePulledAtomsLocked(const vector<std::shared_ptr<LogEve
mProto.clear();
int count = 0;
for (const auto& event : data) {
- if (matchesSimple(*mUidMap, matcher, *event)) {
+ if (matchesSimple(mUidMap, matcher, *event)) {
count++;
uint64_t atomToken = mProto.start(util::FIELD_TYPE_MESSAGE |
util::FIELD_COUNT_REPEATED | FIELD_ID_ATOM);
@@ -209,7 +209,7 @@ void ShellSubscriber::onLogEvent(const LogEvent& event) {
mProto.clear();
for (const auto& matcher : mSubscriptionInfo->mPushedMatchers) {
- if (matchesSimple(*mUidMap, matcher, event)) {
+ if (matchesSimple(mUidMap, matcher, event)) {
uint64_t atomToken = mProto.start(util::FIELD_TYPE_MESSAGE |
util::FIELD_COUNT_REPEATED | FIELD_ID_ATOM);
event.ToProto(mProto);
diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp
index 6264c075426a..92cd04f37ee0 100644
--- a/cmds/statsd/tests/LogEntryMatcher_test.cpp
+++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp
@@ -110,7 +110,7 @@ void makeBoolLogEvent(LogEvent* logEvent, const int32_t atomId, const int64_t ti
} // anonymous namespace
TEST(AtomMatcherTest, TestSimpleMatcher) {
- UidMap uidMap;
+ sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
@@ -129,7 +129,7 @@ TEST(AtomMatcherTest, TestSimpleMatcher) {
}
TEST(AtomMatcherTest, TestAttributionMatcher) {
- UidMap uidMap;
+ sp<UidMap> uidMap = new UidMap();
std::vector<int> attributionUids = {1111, 2222, 3333};
std::vector<string> attributionTags = {"location1", "location2", "location3"};
@@ -204,7 +204,7 @@ TEST(AtomMatcherTest, TestAttributionMatcher) {
"pkg0");
EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
- uidMap.updateMap(
+ uidMap->updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("v1"), android::String16("v1"), android::String16("v2"),
android::String16("v1"), android::String16("v2")},
@@ -356,8 +356,8 @@ TEST(AtomMatcherTest, TestAttributionMatcher) {
}
TEST(AtomMatcherTest, TestUidFieldMatcher) {
- UidMap uidMap;
- uidMap.updateMap(
+ sp<UidMap> uidMap = new UidMap();
+ uidMap->updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("v1"), android::String16("v1"), android::String16("v2"),
android::String16("v1"), android::String16("v2")},
@@ -392,8 +392,8 @@ TEST(AtomMatcherTest, TestUidFieldMatcher) {
}
TEST(AtomMatcherTest, TestNeqAnyStringMatcher) {
- UidMap uidMap;
- uidMap.updateMap(
+ sp<UidMap> uidMap = new UidMap();
+ uidMap->updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("v1"), android::String16("v1"), android::String16("v2"),
android::String16("v1"), android::String16("v2")},
@@ -453,8 +453,8 @@ TEST(AtomMatcherTest, TestNeqAnyStringMatcher) {
}
TEST(AtomMatcherTest, TestEqAnyStringMatcher) {
- UidMap uidMap;
- uidMap.updateMap(
+ sp<UidMap> uidMap = new UidMap();
+ uidMap->updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("v1"), android::String16("v1"), android::String16("v2"),
android::String16("v1"), android::String16("v2")},
@@ -517,7 +517,7 @@ TEST(AtomMatcherTest, TestEqAnyStringMatcher) {
}
TEST(AtomMatcherTest, TestBoolMatcher) {
- UidMap uidMap;
+ sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
auto simpleMatcher = matcher.mutable_simple_atom_matcher();
@@ -550,7 +550,7 @@ TEST(AtomMatcherTest, TestBoolMatcher) {
}
TEST(AtomMatcherTest, TestStringMatcher) {
- UidMap uidMap;
+ sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
auto simpleMatcher = matcher.mutable_simple_atom_matcher();
@@ -568,7 +568,7 @@ TEST(AtomMatcherTest, TestStringMatcher) {
}
TEST(AtomMatcherTest, TestMultiFieldsMatcher) {
- UidMap uidMap;
+ sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
auto simpleMatcher = matcher.mutable_simple_atom_matcher();
@@ -597,7 +597,7 @@ TEST(AtomMatcherTest, TestMultiFieldsMatcher) {
}
TEST(AtomMatcherTest, TestIntComparisonMatcher) {
- UidMap uidMap;
+ sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
auto simpleMatcher = matcher.mutable_simple_atom_matcher();
@@ -654,7 +654,7 @@ TEST(AtomMatcherTest, TestIntComparisonMatcher) {
}
TEST(AtomMatcherTest, TestFloatComparisonMatcher) {
- UidMap uidMap;
+ sp<UidMap> uidMap = new UidMap();
// Set up the matcher
AtomMatcher matcher;
auto simpleMatcher = matcher.mutable_simple_atom_matcher();
diff --git a/cmds/statsd/tests/MetricsManager_test.cpp b/cmds/statsd/tests/MetricsManager_test.cpp
index 6259757fe092..8dd608347064 100644
--- a/cmds/statsd/tests/MetricsManager_test.cpp
+++ b/cmds/statsd/tests/MetricsManager_test.cpp
@@ -28,7 +28,7 @@
#include "src/metrics/GaugeMetricProducer.h"
#include "src/metrics/MetricProducer.h"
#include "src/metrics/ValueMetricProducer.h"
-#include "src/metrics/metrics_manager_util.h"
+#include "src/metrics/parsing_utils/metrics_manager_util.h"
#include "src/state/StateManager.h"
#include "statsd_test_util.h"
@@ -48,7 +48,6 @@ namespace statsd {
namespace {
const ConfigKey kConfigKey(0, 12345);
-const long kAlertId = 3;
const long timeBaseSec = 1000;
@@ -90,287 +89,6 @@ StatsdConfig buildGoodConfig() {
metric->set_bucket(ONE_MINUTE);
metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/);
metric->mutable_dimensions_in_what()->add_child()->set_field(1);
-
- config.add_no_report_metric(3);
-
- auto alert = config.add_alert();
- alert->set_id(kAlertId);
- alert->set_metric_id(3);
- alert->set_num_buckets(10);
- alert->set_refractory_period_secs(100);
- alert->set_trigger_if_sum_gt(100);
- return config;
-}
-
-StatsdConfig buildCircleMatchers() {
- StatsdConfig config;
- config.set_id(12345);
-
- AtomMatcher* eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
-
- SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
- simpleAtomMatcher->add_field_value_matcher()->set_field(
- 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
- simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
- 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
-
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
-
- AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
- combination->set_operation(LogicalOperation::OR);
- combination->add_matcher(StringToId("SCREEN_IS_ON"));
- // Circle dependency
- combination->add_matcher(StringToId("SCREEN_ON_OR_OFF"));
-
- return config;
-}
-
-StatsdConfig buildAlertWithUnknownMetric() {
- StatsdConfig config;
- config.set_id(12345);
-
- AtomMatcher* eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
-
- CountMetric* metric = config.add_count_metric();
- metric->set_id(3);
- metric->set_what(StringToId("SCREEN_IS_ON"));
- metric->set_bucket(ONE_MINUTE);
- metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/);
- metric->mutable_dimensions_in_what()->add_child()->set_field(1);
-
- auto alert = config.add_alert();
- alert->set_id(3);
- alert->set_metric_id(2);
- alert->set_num_buckets(10);
- alert->set_refractory_period_secs(100);
- alert->set_trigger_if_sum_gt(100);
- return config;
-}
-
-StatsdConfig buildMissingMatchers() {
- StatsdConfig config;
- config.set_id(12345);
-
- AtomMatcher* eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
-
- SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
- simpleAtomMatcher->add_field_value_matcher()->set_field(
- 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
- simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
- 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
-
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
-
- AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
- combination->set_operation(LogicalOperation::OR);
- combination->add_matcher(StringToId("SCREEN_IS_ON"));
- // undefined matcher
- combination->add_matcher(StringToId("ABC"));
-
- return config;
-}
-
-StatsdConfig buildMissingPredicate() {
- StatsdConfig config;
- config.set_id(12345);
-
- CountMetric* metric = config.add_count_metric();
- metric->set_id(3);
- metric->set_what(StringToId("SCREEN_EVENT"));
- metric->set_bucket(ONE_MINUTE);
- metric->set_condition(StringToId("SOME_CONDITION"));
-
- AtomMatcher* eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_EVENT"));
-
- SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2);
-
- return config;
-}
-
-StatsdConfig buildDimensionMetricsWithMultiTags() {
- StatsdConfig config;
- config.set_id(12345);
-
- AtomMatcher* eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("BATTERY_VERY_LOW"));
- SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2);
-
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("BATTERY_VERY_VERY_LOW"));
- simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(3);
-
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("BATTERY_LOW"));
-
- AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
- combination->set_operation(LogicalOperation::OR);
- combination->add_matcher(StringToId("BATTERY_VERY_LOW"));
- combination->add_matcher(StringToId("BATTERY_VERY_VERY_LOW"));
-
- // Count process state changes, slice by uid, while SCREEN_IS_OFF
- CountMetric* metric = config.add_count_metric();
- metric->set_id(3);
- metric->set_what(StringToId("BATTERY_LOW"));
- metric->set_bucket(ONE_MINUTE);
- // This case is interesting. We want to dimension across two atoms.
- metric->mutable_dimensions_in_what()->add_child()->set_field(1);
-
- auto alert = config.add_alert();
- alert->set_id(kAlertId);
- alert->set_metric_id(3);
- alert->set_num_buckets(10);
- alert->set_refractory_period_secs(100);
- alert->set_trigger_if_sum_gt(100);
- return config;
-}
-
-StatsdConfig buildCirclePredicates() {
- StatsdConfig config;
- config.set_id(12345);
-
- AtomMatcher* eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
-
- SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
- simpleAtomMatcher->add_field_value_matcher()->set_field(
- 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
- simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
- 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
-
- eventMatcher = config.add_atom_matcher();
- eventMatcher->set_id(StringToId("SCREEN_IS_OFF"));
-
- simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
- simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
- simpleAtomMatcher->add_field_value_matcher()->set_field(
- 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
- simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
- 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/);
-
- auto condition = config.add_predicate();
- condition->set_id(StringToId("SCREEN_IS_ON"));
- SimplePredicate* simplePredicate = condition->mutable_simple_predicate();
- simplePredicate->set_start(StringToId("SCREEN_IS_ON"));
- simplePredicate->set_stop(StringToId("SCREEN_IS_OFF"));
-
- condition = config.add_predicate();
- condition->set_id(StringToId("SCREEN_IS_EITHER_ON_OFF"));
-
- Predicate_Combination* combination = condition->mutable_combination();
- combination->set_operation(LogicalOperation::OR);
- combination->add_predicate(StringToId("SCREEN_IS_ON"));
- combination->add_predicate(StringToId("SCREEN_IS_EITHER_ON_OFF"));
-
- return config;
-}
-
-StatsdConfig buildConfigWithDifferentPredicates() {
- StatsdConfig config;
- config.set_id(12345);
-
- auto pulledAtomMatcher =
- CreateSimpleAtomMatcher("SUBSYSTEM_SLEEP", util::SUBSYSTEM_SLEEP_STATE);
- *config.add_atom_matcher() = pulledAtomMatcher;
- auto screenOnAtomMatcher = CreateScreenTurnedOnAtomMatcher();
- *config.add_atom_matcher() = screenOnAtomMatcher;
- auto screenOffAtomMatcher = CreateScreenTurnedOffAtomMatcher();
- *config.add_atom_matcher() = screenOffAtomMatcher;
- auto batteryNoneAtomMatcher = CreateBatteryStateNoneMatcher();
- *config.add_atom_matcher() = batteryNoneAtomMatcher;
- auto batteryUsbAtomMatcher = CreateBatteryStateUsbMatcher();
- *config.add_atom_matcher() = batteryUsbAtomMatcher;
-
- // Simple condition with InitialValue set to default (unknown).
- auto screenOnUnknownPredicate = CreateScreenIsOnPredicate();
- *config.add_predicate() = screenOnUnknownPredicate;
-
- // Simple condition with InitialValue set to false.
- auto screenOnFalsePredicate = config.add_predicate();
- screenOnFalsePredicate->set_id(StringToId("ScreenIsOnInitialFalse"));
- SimplePredicate* simpleScreenOnFalsePredicate =
- screenOnFalsePredicate->mutable_simple_predicate();
- simpleScreenOnFalsePredicate->set_start(screenOnAtomMatcher.id());
- simpleScreenOnFalsePredicate->set_stop(screenOffAtomMatcher.id());
- simpleScreenOnFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE);
-
- // Simple condition with InitialValue set to false.
- auto onBatteryFalsePredicate = config.add_predicate();
- onBatteryFalsePredicate->set_id(StringToId("OnBatteryInitialFalse"));
- SimplePredicate* simpleOnBatteryFalsePredicate =
- onBatteryFalsePredicate->mutable_simple_predicate();
- simpleOnBatteryFalsePredicate->set_start(batteryNoneAtomMatcher.id());
- simpleOnBatteryFalsePredicate->set_stop(batteryUsbAtomMatcher.id());
- simpleOnBatteryFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE);
-
- // Combination condition with both simple condition InitialValues set to false.
- auto screenOnFalseOnBatteryFalsePredicate = config.add_predicate();
- screenOnFalseOnBatteryFalsePredicate->set_id(StringToId("ScreenOnFalseOnBatteryFalse"));
- screenOnFalseOnBatteryFalsePredicate->mutable_combination()->set_operation(
- LogicalOperation::AND);
- addPredicateToPredicateCombination(*screenOnFalsePredicate,
- screenOnFalseOnBatteryFalsePredicate);
- addPredicateToPredicateCombination(*onBatteryFalsePredicate,
- screenOnFalseOnBatteryFalsePredicate);
-
- // Combination condition with one simple condition InitialValue set to unknown and one set to
- // false.
- auto screenOnUnknownOnBatteryFalsePredicate = config.add_predicate();
- screenOnUnknownOnBatteryFalsePredicate->set_id(StringToId("ScreenOnUnknowneOnBatteryFalse"));
- screenOnUnknownOnBatteryFalsePredicate->mutable_combination()->set_operation(
- LogicalOperation::AND);
- addPredicateToPredicateCombination(screenOnUnknownPredicate,
- screenOnUnknownOnBatteryFalsePredicate);
- addPredicateToPredicateCombination(*onBatteryFalsePredicate,
- screenOnUnknownOnBatteryFalsePredicate);
-
- // Simple condition metric with initial value false.
- ValueMetric* metric1 = config.add_value_metric();
- metric1->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialFalse"));
- metric1->set_what(pulledAtomMatcher.id());
- *metric1->mutable_value_field() =
- CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
- metric1->set_bucket(FIVE_MINUTES);
- metric1->set_condition(screenOnFalsePredicate->id());
-
- // Simple condition metric with initial value unknown.
- ValueMetric* metric2 = config.add_value_metric();
- metric2->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialUnknown"));
- metric2->set_what(pulledAtomMatcher.id());
- *metric2->mutable_value_field() =
- CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
- metric2->set_bucket(FIVE_MINUTES);
- metric2->set_condition(screenOnUnknownPredicate.id());
-
- // Combination condition metric with initial values false and false.
- ValueMetric* metric3 = config.add_value_metric();
- metric3->set_id(StringToId("ValueSubsystemSleepWhileScreenOnFalseDeviceUnpluggedFalse"));
- metric3->set_what(pulledAtomMatcher.id());
- *metric3->mutable_value_field() =
- CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
- metric3->set_bucket(FIVE_MINUTES);
- metric3->set_condition(screenOnFalseOnBatteryFalsePredicate->id());
-
- // Combination condition metric with initial values unknown and false.
- ValueMetric* metric4 = config.add_value_metric();
- metric4->set_id(StringToId("ValueSubsystemSleepWhileScreenOnUnknownDeviceUnpluggedFalse"));
- metric4->set_what(pulledAtomMatcher.id());
- *metric4->mutable_value_field() =
- CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
- metric4->set_bucket(FIVE_MINUTES);
- metric4->set_condition(screenOnUnknownOnBatteryFalsePredicate->id());
-
return config;
}
@@ -379,274 +97,6 @@ bool isSubset(const set<int32_t>& set1, const set<int32_t>& set2) {
}
} // anonymous namespace
-TEST(MetricsManagerTest, TestInitialConditions) {
- UidMap uidMap;
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildConfigWithDifferentPredicates();
- set<int> allTagIds;
- vector<sp<LogMatchingTracker>> allAtomMatchers;
- vector<sp<ConditionTracker>> allConditionTrackers;
- vector<sp<MetricProducer>> allMetricProducers;
- std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
- std::vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, std::vector<int>> conditionToMetricMap;
- unordered_map<int, std::vector<int>> trackerToMetricMap;
- unordered_map<int, std::vector<int>> trackerToConditionMap;
- unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_TRUE(initStatsdConfig(
- kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
- timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, allConditionTrackers,
- allMetricProducers, allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap, activationAtomTrackerToMetricMap,
- deactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
- noReportMetricIds));
- ASSERT_EQ(4u, allMetricProducers.size());
- ASSERT_EQ(5u, allConditionTrackers.size());
-
- ConditionKey queryKey;
- vector<ConditionState> conditionCache(5, ConditionState::kNotEvaluated);
-
- allConditionTrackers[3]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache);
- allConditionTrackers[4]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache);
- EXPECT_EQ(ConditionState::kUnknown, conditionCache[0]);
- EXPECT_EQ(ConditionState::kFalse, conditionCache[1]);
- EXPECT_EQ(ConditionState::kFalse, conditionCache[2]);
- EXPECT_EQ(ConditionState::kFalse, conditionCache[3]);
- EXPECT_EQ(ConditionState::kUnknown, conditionCache[4]);
-
- EXPECT_EQ(ConditionState::kFalse, allMetricProducers[0]->mCondition);
- EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[1]->mCondition);
- EXPECT_EQ(ConditionState::kFalse, allMetricProducers[2]->mCondition);
- EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[3]->mCondition);
-}
-
-TEST(MetricsManagerTest, TestGoodConfig) {
- UidMap uidMap;
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildGoodConfig();
- set<int> allTagIds;
- vector<sp<LogMatchingTracker>> allAtomMatchers;
- vector<sp<ConditionTracker>> allConditionTrackers;
- vector<sp<MetricProducer>> allMetricProducers;
- std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
- std::vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, std::vector<int>> conditionToMetricMap;
- unordered_map<int, std::vector<int>> trackerToMetricMap;
- unordered_map<int, std::vector<int>> trackerToConditionMap;
- unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_TRUE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
- periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
- allAtomMatchers, allConditionTrackers, allMetricProducers,
- allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- alertTrackerMap, metricsWithActivation,
- noReportMetricIds));
- ASSERT_EQ(1u, allMetricProducers.size());
- ASSERT_EQ(1u, allAnomalyTrackers.size());
- ASSERT_EQ(1u, noReportMetricIds.size());
- ASSERT_EQ(1u, alertTrackerMap.size());
- EXPECT_NE(alertTrackerMap.find(kAlertId), alertTrackerMap.end());
- EXPECT_EQ(alertTrackerMap.find(kAlertId)->second, 0);
-}
-
-TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) {
- UidMap uidMap;
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildDimensionMetricsWithMultiTags();
- set<int> allTagIds;
- vector<sp<LogMatchingTracker>> allAtomMatchers;
- vector<sp<ConditionTracker>> allConditionTrackers;
- vector<sp<MetricProducer>> allMetricProducers;
- std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
- std::vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, std::vector<int>> conditionToMetricMap;
- unordered_map<int, std::vector<int>> trackerToMetricMap;
- unordered_map<int, std::vector<int>> trackerToConditionMap;
- unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
- periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
- allAtomMatchers, allConditionTrackers, allMetricProducers,
- allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- alertTrackerMap, metricsWithActivation,
- noReportMetricIds));
-}
-
-TEST(MetricsManagerTest, TestCircleLogMatcherDependency) {
- UidMap uidMap;
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildCircleMatchers();
- set<int> allTagIds;
- vector<sp<LogMatchingTracker>> allAtomMatchers;
- vector<sp<ConditionTracker>> allConditionTrackers;
- vector<sp<MetricProducer>> allMetricProducers;
- std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
- std::vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, std::vector<int>> conditionToMetricMap;
- unordered_map<int, std::vector<int>> trackerToMetricMap;
- unordered_map<int, std::vector<int>> trackerToConditionMap;
- unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
- periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
- allAtomMatchers, allConditionTrackers, allMetricProducers,
- allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- alertTrackerMap, metricsWithActivation,
- noReportMetricIds));
-}
-
-TEST(MetricsManagerTest, TestMissingMatchers) {
- UidMap uidMap;
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildMissingMatchers();
- set<int> allTagIds;
- vector<sp<LogMatchingTracker>> allAtomMatchers;
- vector<sp<ConditionTracker>> allConditionTrackers;
- vector<sp<MetricProducer>> allMetricProducers;
- std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
- std::vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, std::vector<int>> conditionToMetricMap;
- unordered_map<int, std::vector<int>> trackerToMetricMap;
- unordered_map<int, std::vector<int>> trackerToConditionMap;
- unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- std::set<int64_t> noReportMetricIds;
- EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
- periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
- allAtomMatchers, allConditionTrackers, allMetricProducers,
- allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- alertTrackerMap, metricsWithActivation,
- noReportMetricIds));
-}
-
-TEST(MetricsManagerTest, TestMissingPredicate) {
- UidMap uidMap;
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildMissingPredicate();
- set<int> allTagIds;
- vector<sp<LogMatchingTracker>> allAtomMatchers;
- vector<sp<ConditionTracker>> allConditionTrackers;
- vector<sp<MetricProducer>> allMetricProducers;
- std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
- std::vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, std::vector<int>> conditionToMetricMap;
- unordered_map<int, std::vector<int>> trackerToMetricMap;
- unordered_map<int, std::vector<int>> trackerToConditionMap;
- unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- std::set<int64_t> noReportMetricIds;
- EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
- periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
- allAtomMatchers, allConditionTrackers, allMetricProducers,
- allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- alertTrackerMap, metricsWithActivation, noReportMetricIds));
-}
-
-TEST(MetricsManagerTest, TestCirclePredicateDependency) {
- UidMap uidMap;
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildCirclePredicates();
- set<int> allTagIds;
- vector<sp<LogMatchingTracker>> allAtomMatchers;
- vector<sp<ConditionTracker>> allConditionTrackers;
- vector<sp<MetricProducer>> allMetricProducers;
- std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
- std::vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, std::vector<int>> conditionToMetricMap;
- unordered_map<int, std::vector<int>> trackerToMetricMap;
- unordered_map<int, std::vector<int>> trackerToConditionMap;
- unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
- periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
- allAtomMatchers, allConditionTrackers, allMetricProducers,
- allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- alertTrackerMap, metricsWithActivation,
- noReportMetricIds));
-}
-
-TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
- UidMap uidMap;
- sp<StatsPullerManager> pullerManager = new StatsPullerManager();
- sp<AlarmMonitor> anomalyAlarmMonitor;
- sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildAlertWithUnknownMetric();
- set<int> allTagIds;
- vector<sp<LogMatchingTracker>> allAtomMatchers;
- vector<sp<ConditionTracker>> allConditionTrackers;
- vector<sp<MetricProducer>> allMetricProducers;
- std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
- std::vector<sp<AlarmTracker>> allAlarmTrackers;
- unordered_map<int, std::vector<int>> conditionToMetricMap;
- unordered_map<int, std::vector<int>> trackerToMetricMap;
- unordered_map<int, std::vector<int>> trackerToConditionMap;
- unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
- unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
- unordered_map<int64_t, int> alertTrackerMap;
- vector<int> metricsWithActivation;
- std::set<int64_t> noReportMetricIds;
-
- EXPECT_FALSE(initStatsdConfig(kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor,
- periodicAlarmMonitor, timeBaseSec, timeBaseSec, allTagIds,
- allAtomMatchers, allConditionTrackers, allMetricProducers,
- allAnomalyTrackers, allAlarmTrackers, conditionToMetricMap,
- trackerToMetricMap, trackerToConditionMap,
- activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
- alertTrackerMap, metricsWithActivation,
- noReportMetricIds));
-}
-
TEST(MetricsManagerTest, TestLogSources) {
string app1 = "app1";
set<int32_t> app1Uids = {1111, 11111};
@@ -680,7 +130,7 @@ TEST(MetricsManagerTest, TestLogSources) {
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildGoodConfig();
+ StatsdConfig config;
config.add_allowed_log_source("AID_SYSTEM");
config.add_allowed_log_source(app1);
config.add_default_pull_packages("AID_SYSTEM");
@@ -744,7 +194,7 @@ TEST(MetricsManagerTest, TestCheckLogCredentialsWhitelistedAtom) {
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> periodicAlarmMonitor;
- StatsdConfig config = buildGoodConfig();
+ StatsdConfig config;
config.add_whitelisted_atom_ids(3);
config.add_whitelisted_atom_ids(4);
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index caea42dfe032..d96ff8a1925b 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -47,7 +47,6 @@ namespace {
const ConfigKey kConfigKey(0, 12345);
const int tagId = 1;
const int64_t metricId = 123;
-const int64_t atomMatcherId = 678;
const int logEventMatcherIndex = 0;
const int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
@@ -94,11 +93,8 @@ TEST(GaugeMetricProducerTest, TestFirstBucket) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
- new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<EventMatcherWizard> eventMatcherWizard =
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -127,12 +123,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
@@ -217,12 +209,8 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPushedEvents) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
wizard, logEventMatcherIndex, eventMatcherWizard,
@@ -301,12 +289,9 @@ TEST_P(GaugeMetricProducerTest_PartialBucket, TestPulled) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
+
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, kConfigKey, _)).WillOnce(Return());
@@ -378,12 +363,8 @@ TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
@@ -428,12 +409,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
int64_t conditionChangeNs = bucketStartTimeNs + 8;
@@ -502,12 +479,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) {
dim->set_field(tagId);
dim->add_child()->set_field(1);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*wizard, query(_, _, _))
@@ -577,12 +550,8 @@ TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
gaugeFieldMatcher->set_field(tagId);
gaugeFieldMatcher->add_child()->set_field(2);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, {},
wizard, logEventMatcherIndex, eventMatcherWizard, tagId, -1,
@@ -657,12 +626,8 @@ TEST(GaugeMetricProducerTest, TestPullOnTrigger) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
@@ -729,12 +694,8 @@ TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, _, _))
@@ -807,12 +768,8 @@ TEST(GaugeMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, Pull(tagId, kConfigKey, bucketStartTimeNs + 3, _))
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index 98892507e78d..5524ebc86b36 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -46,7 +46,6 @@ namespace {
const ConfigKey kConfigKey(0, 12345);
const int tagId = 1;
const int64_t metricId = 123;
-const int64_t atomMatcherId = 678;
const int logEventMatcherIndex = 0;
const int64_t bucketStartTimeNs = 10000000000;
const int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
@@ -99,12 +98,8 @@ class ValueMetricProducerTestHelper {
public:
static sp<ValueMetricProducer> createValueProducerNoConditions(
sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
.WillOnce(Return());
@@ -122,12 +117,8 @@ public:
static sp<ValueMetricProducer> createValueProducerWithCondition(
sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
ConditionState conditionAfterFirstBucketPrepared) {
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
.WillOnce(Return());
@@ -147,12 +138,8 @@ public:
sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
vector<int32_t> slicedStateAtoms,
unordered_map<int, unordered_map<int, int64_t>> stateGroupMap) {
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
.WillOnce(Return());
@@ -172,12 +159,8 @@ public:
vector<int32_t> slicedStateAtoms,
unordered_map<int, unordered_map<int, int64_t>> stateGroupMap,
ConditionState conditionAfterFirstBucketPrepared) {
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _))
.WillOnce(Return());
@@ -237,12 +220,8 @@ TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
int64_t startTimeBase = 11;
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -267,12 +246,8 @@ TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
TEST(ValueMetricProducerTest, TestFirstBucket) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -421,15 +396,11 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPartialBucketCreated) {
TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- auto keyValue = atomMatcher.add_field_value_matcher();
- keyValue->set_field(1);
- keyValue->set_eq_int(3);
+ FieldValueMatcher fvm;
+ fvm.set_field(1);
+ fvm.set_eq_int(3);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex, {fvm});
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
@@ -698,12 +669,8 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
TEST_P(ValueMetricProducerTest_PartialBucket, TestPushedEvents) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -759,12 +726,8 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPushedEvents) {
TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValue) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
int64_t partialBucketSplitTimeNs = bucket2StartTimeNs + 150;
@@ -820,12 +783,8 @@ TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_split_bucket_for_app_upgrade(false);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
@@ -900,12 +859,8 @@ TEST_P(ValueMetricProducerTest_PartialBucket, TestPulledValueWhileConditionFalse
TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -944,12 +899,8 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -1015,12 +966,8 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -1360,12 +1307,8 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::MIN);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -1404,12 +1347,8 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::MAX);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -1447,12 +1386,8 @@ TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::AVG);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -1495,12 +1430,8 @@ TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::SUM);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -1539,12 +1470,8 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
metric.set_aggregation_type(ValueMetric::MIN);
metric.set_use_diff(true);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -1611,12 +1538,8 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
metric.set_aggregation_type(ValueMetric::MIN);
metric.set_use_diff(true);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
@@ -2140,12 +2063,8 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
@@ -2963,12 +2882,8 @@ TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
@@ -3001,12 +2916,8 @@ TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
@@ -3045,12 +2956,8 @@ TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ createEventMatcherWizard(tagId, logEventMatcherIndex);
sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, kConfigKey, _, _, _)).WillOnce(Return());
diff --git a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
new file mode 100644
index 000000000000..6b50fe5387d7
--- /dev/null
+++ b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
@@ -0,0 +1,382 @@
+// Copyright (C) 2020 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.
+
+#include "src/metrics/parsing_utils/config_update_utils.h"
+
+#include <gtest/gtest.h>
+#include <private/android_filesystem_config.h>
+#include <stdio.h>
+
+#include <set>
+#include <unordered_map>
+#include <vector>
+
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "src/metrics/parsing_utils/metrics_manager_util.h"
+#include "tests/statsd_test_util.h"
+
+using namespace testing;
+using android::sp;
+using android::os::statsd::Predicate;
+using std::map;
+using std::set;
+using std::unordered_map;
+using std::vector;
+
+#ifdef __ANDROID__
+
+namespace android {
+namespace os {
+namespace statsd {
+
+namespace {
+
+ConfigKey key(123, 456);
+const int64_t timeBaseNs = 1000;
+sp<UidMap> uidMap = new UidMap();
+sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+sp<AlarmMonitor> anomalyAlarmMonitor;
+sp<AlarmMonitor> periodicAlarmMonitor;
+set<int> allTagIds;
+vector<sp<LogMatchingTracker>> oldAtomMatchers;
+unordered_map<int64_t, int> oldLogTrackerMap;
+vector<sp<ConditionTracker>> oldConditionTrackers;
+vector<sp<MetricProducer>> oldMetricProducers;
+std::vector<sp<AnomalyTracker>> oldAnomalyTrackers;
+std::vector<sp<AlarmTracker>> oldAlarmTrackers;
+unordered_map<int, std::vector<int>> conditionToMetricMap;
+unordered_map<int, std::vector<int>> trackerToMetricMap;
+unordered_map<int, std::vector<int>> trackerToConditionMap;
+unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+unordered_map<int64_t, int> alertTrackerMap;
+vector<int> metricsWithActivation;
+std::set<int64_t> noReportMetricIds;
+
+class ConfigUpdateTest : public ::testing::Test {
+public:
+ ConfigUpdateTest() {
+ }
+
+ void SetUp() override {
+ allTagIds.clear();
+ oldAtomMatchers.clear();
+ oldLogTrackerMap.clear();
+ oldConditionTrackers.clear();
+ oldMetricProducers.clear();
+ oldAnomalyTrackers.clear();
+ oldAlarmTrackers.clear();
+ conditionToMetricMap.clear();
+ trackerToMetricMap.clear();
+ trackerToConditionMap.clear();
+ activationAtomTrackerToMetricMap.clear();
+ deactivationAtomTrackerToMetricMap.clear();
+ alertTrackerMap.clear();
+ metricsWithActivation.clear();
+ noReportMetricIds.clear();
+ }
+};
+
+bool initConfig(const StatsdConfig& config) {
+ return initStatsdConfig(key, config, uidMap, pullerManager, anomalyAlarmMonitor,
+ periodicAlarmMonitor, timeBaseNs, timeBaseNs, allTagIds,
+ oldAtomMatchers, oldLogTrackerMap, oldConditionTrackers,
+ oldMetricProducers, oldAnomalyTrackers, oldAlarmTrackers,
+ conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ alertTrackerMap, metricsWithActivation, noReportMetricIds);
+}
+
+} // anonymous namespace
+
+TEST_F(ConfigUpdateTest, TestSimpleMatcherPreserve) {
+ StatsdConfig config;
+ AtomMatcher matcher = CreateSimpleAtomMatcher("TEST", /*atom=*/10);
+ int64_t matcherId = matcher.id();
+ *config.add_atom_matcher() = matcher;
+
+ // Create an initial config.
+ EXPECT_TRUE(initConfig(config));
+
+ vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(1, false);
+ unordered_map<int64_t, int> newLogTrackerMap;
+ newLogTrackerMap[matcherId] = 0;
+ EXPECT_TRUE(determineMatcherUpdateStatus(config, 0, oldLogTrackerMap, oldAtomMatchers,
+ newLogTrackerMap, matchersToUpdate, cycleTracker));
+ EXPECT_EQ(matchersToUpdate[0], UPDATE_PRESERVE);
+}
+
+TEST_F(ConfigUpdateTest, TestSimpleMatcherReplace) {
+ StatsdConfig config;
+ AtomMatcher matcher = CreateSimpleAtomMatcher("TEST", /*atom=*/10);
+ *config.add_atom_matcher() = matcher;
+
+ EXPECT_TRUE(initConfig(config));
+
+ StatsdConfig newConfig;
+ // Same id, different atom, so should be replaced.
+ AtomMatcher newMatcher = CreateSimpleAtomMatcher("TEST", /*atom=*/11);
+ int64_t matcherId = newMatcher.id();
+ EXPECT_EQ(matcherId, matcher.id());
+ *newConfig.add_atom_matcher() = newMatcher;
+
+ vector<UpdateStatus> matchersToUpdate(1, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(1, false);
+ unordered_map<int64_t, int> newLogTrackerMap;
+ newLogTrackerMap[matcherId] = 0;
+ EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 0, oldLogTrackerMap, oldAtomMatchers,
+ newLogTrackerMap, matchersToUpdate, cycleTracker));
+ EXPECT_EQ(matchersToUpdate[0], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestCombinationMatcherPreserve) {
+ StatsdConfig config;
+ AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10);
+ int64_t matcher1Id = matcher1.id();
+ *config.add_atom_matcher() = matcher1;
+
+ AtomMatcher matcher2 = CreateSimpleAtomMatcher("TEST2", /*atom=*/11);
+ *config.add_atom_matcher() = matcher2;
+ int64_t matcher2Id = matcher2.id();
+
+ AtomMatcher matcher3;
+ matcher3.set_id(StringToId("TEST3"));
+ AtomMatcher_Combination* combination = matcher3.mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_matcher(matcher1Id);
+ combination->add_matcher(matcher2Id);
+ int64_t matcher3Id = matcher3.id();
+ *config.add_atom_matcher() = matcher3;
+
+ EXPECT_TRUE(initConfig(config));
+
+ StatsdConfig newConfig;
+ unordered_map<int64_t, int> newLogTrackerMap;
+ // Same matchers, different order, all should be preserved.
+ *newConfig.add_atom_matcher() = matcher2;
+ newLogTrackerMap[matcher2Id] = 0;
+ *newConfig.add_atom_matcher() = matcher3;
+ newLogTrackerMap[matcher3Id] = 1;
+ *newConfig.add_atom_matcher() = matcher1;
+ newLogTrackerMap[matcher1Id] = 2;
+
+ vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(3, false);
+ // Only update the combination. It should recurse the two child matchers and preserve all 3.
+ EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldLogTrackerMap, oldAtomMatchers,
+ newLogTrackerMap, matchersToUpdate, cycleTracker));
+ EXPECT_EQ(matchersToUpdate[0], UPDATE_PRESERVE);
+ EXPECT_EQ(matchersToUpdate[1], UPDATE_PRESERVE);
+ EXPECT_EQ(matchersToUpdate[2], UPDATE_PRESERVE);
+}
+
+TEST_F(ConfigUpdateTest, TestCombinationMatcherReplace) {
+ StatsdConfig config;
+ AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10);
+ int64_t matcher1Id = matcher1.id();
+ *config.add_atom_matcher() = matcher1;
+
+ AtomMatcher matcher2 = CreateSimpleAtomMatcher("TEST2", /*atom=*/11);
+ *config.add_atom_matcher() = matcher2;
+ int64_t matcher2Id = matcher2.id();
+
+ AtomMatcher matcher3;
+ matcher3.set_id(StringToId("TEST3"));
+ AtomMatcher_Combination* combination = matcher3.mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_matcher(matcher1Id);
+ combination->add_matcher(matcher2Id);
+ int64_t matcher3Id = matcher3.id();
+ *config.add_atom_matcher() = matcher3;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Change the logical operation of the combination matcher, causing a replacement.
+ matcher3.mutable_combination()->set_operation(LogicalOperation::AND);
+
+ StatsdConfig newConfig;
+ unordered_map<int64_t, int> newLogTrackerMap;
+ *newConfig.add_atom_matcher() = matcher2;
+ newLogTrackerMap[matcher2Id] = 0;
+ *newConfig.add_atom_matcher() = matcher3;
+ newLogTrackerMap[matcher3Id] = 1;
+ *newConfig.add_atom_matcher() = matcher1;
+ newLogTrackerMap[matcher1Id] = 2;
+
+ vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(3, false);
+ // Only update the combination. The simple matchers should not be evaluated.
+ EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldLogTrackerMap, oldAtomMatchers,
+ newLogTrackerMap, matchersToUpdate, cycleTracker));
+ EXPECT_EQ(matchersToUpdate[0], UPDATE_UNKNOWN);
+ EXPECT_EQ(matchersToUpdate[1], UPDATE_REPLACE);
+ EXPECT_EQ(matchersToUpdate[2], UPDATE_UNKNOWN);
+}
+
+TEST_F(ConfigUpdateTest, TestCombinationMatcherDepsChange) {
+ StatsdConfig config;
+ AtomMatcher matcher1 = CreateSimpleAtomMatcher("TEST1", /*atom=*/10);
+ int64_t matcher1Id = matcher1.id();
+ *config.add_atom_matcher() = matcher1;
+
+ AtomMatcher matcher2 = CreateSimpleAtomMatcher("TEST2", /*atom=*/11);
+ *config.add_atom_matcher() = matcher2;
+ int64_t matcher2Id = matcher2.id();
+
+ AtomMatcher matcher3;
+ matcher3.set_id(StringToId("TEST3"));
+ AtomMatcher_Combination* combination = matcher3.mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_matcher(matcher1Id);
+ combination->add_matcher(matcher2Id);
+ int64_t matcher3Id = matcher3.id();
+ *config.add_atom_matcher() = matcher3;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Change a dependency of matcher 3.
+ matcher2.mutable_simple_atom_matcher()->set_atom_id(12);
+
+ StatsdConfig newConfig;
+ unordered_map<int64_t, int> newLogTrackerMap;
+ *newConfig.add_atom_matcher() = matcher2;
+ newLogTrackerMap[matcher2Id] = 0;
+ *newConfig.add_atom_matcher() = matcher3;
+ newLogTrackerMap[matcher3Id] = 1;
+ *newConfig.add_atom_matcher() = matcher1;
+ newLogTrackerMap[matcher1Id] = 2;
+
+ vector<UpdateStatus> matchersToUpdate(3, UPDATE_UNKNOWN);
+ vector<bool> cycleTracker(3, false);
+ // Only update the combination.
+ EXPECT_TRUE(determineMatcherUpdateStatus(newConfig, 1, oldLogTrackerMap, oldAtomMatchers,
+ newLogTrackerMap, matchersToUpdate, cycleTracker));
+ // Matcher 2 and matcher3 must be reevaluated. Matcher 1 might, but does not need to be.
+ EXPECT_EQ(matchersToUpdate[0], UPDATE_REPLACE);
+ EXPECT_EQ(matchersToUpdate[1], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestUpdateMatchers) {
+ StatsdConfig config;
+ // Will be preserved.
+ AtomMatcher simple1 = CreateSimpleAtomMatcher("SIMPLE1", /*atom=*/10);
+ int64_t simple1Id = simple1.id();
+ *config.add_atom_matcher() = simple1;
+
+ // Will be replaced.
+ AtomMatcher simple2 = CreateSimpleAtomMatcher("SIMPLE2", /*atom=*/11);
+ *config.add_atom_matcher() = simple2;
+ int64_t simple2Id = simple2.id();
+
+ // Will be removed.
+ AtomMatcher simple3 = CreateSimpleAtomMatcher("SIMPLE3", /*atom=*/12);
+ *config.add_atom_matcher() = simple3;
+ int64_t simple3Id = simple3.id();
+
+ // Will be preserved.
+ AtomMatcher combination1;
+ combination1.set_id(StringToId("combination1"));
+ AtomMatcher_Combination* combination = combination1.mutable_combination();
+ combination->set_operation(LogicalOperation::NOT);
+ combination->add_matcher(simple1Id);
+ int64_t combination1Id = combination1.id();
+ *config.add_atom_matcher() = combination1;
+
+ // Will be replaced since it depends on simple2.
+ AtomMatcher combination2;
+ combination2.set_id(StringToId("combination2"));
+ combination = combination2.mutable_combination();
+ combination->set_operation(LogicalOperation::AND);
+ combination->add_matcher(simple1Id);
+ combination->add_matcher(simple2Id);
+ int64_t combination2Id = combination2.id();
+ *config.add_atom_matcher() = combination2;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Change simple2, causing simple2 and combination2 to be replaced.
+ simple2.mutable_simple_atom_matcher()->set_atom_id(111);
+
+ // 2 new matchers: simple4 and combination3:
+ AtomMatcher simple4 = CreateSimpleAtomMatcher("SIMPLE4", /*atom=*/13);
+ int64_t simple4Id = simple4.id();
+
+ AtomMatcher combination3;
+ combination3.set_id(StringToId("combination3"));
+ combination = combination3.mutable_combination();
+ combination->set_operation(LogicalOperation::AND);
+ combination->add_matcher(simple4Id);
+ combination->add_matcher(simple2Id);
+ int64_t combination3Id = combination3.id();
+
+ StatsdConfig newConfig;
+ *newConfig.add_atom_matcher() = combination3;
+ *newConfig.add_atom_matcher() = simple2;
+ *newConfig.add_atom_matcher() = combination2;
+ *newConfig.add_atom_matcher() = simple1;
+ *newConfig.add_atom_matcher() = simple4;
+ *newConfig.add_atom_matcher() = combination1;
+
+ set<int> newTagIds;
+ unordered_map<int64_t, int> newLogTrackerMap;
+ vector<sp<LogMatchingTracker>> newAtomMatchers;
+ EXPECT_TRUE(updateLogTrackers(newConfig, uidMap, oldLogTrackerMap, oldAtomMatchers, newTagIds,
+ newLogTrackerMap, newAtomMatchers));
+
+ ASSERT_EQ(newTagIds.size(), 3);
+ EXPECT_EQ(newTagIds.count(10), 1);
+ EXPECT_EQ(newTagIds.count(111), 1);
+ EXPECT_EQ(newTagIds.count(13), 1);
+
+ ASSERT_EQ(newLogTrackerMap.size(), 6);
+ EXPECT_EQ(newLogTrackerMap.at(combination3Id), 0);
+ EXPECT_EQ(newLogTrackerMap.at(simple2Id), 1);
+ EXPECT_EQ(newLogTrackerMap.at(combination2Id), 2);
+ EXPECT_EQ(newLogTrackerMap.at(simple1Id), 3);
+ EXPECT_EQ(newLogTrackerMap.at(simple4Id), 4);
+ EXPECT_EQ(newLogTrackerMap.at(combination1Id), 5);
+
+ ASSERT_EQ(newAtomMatchers.size(), 6);
+ // Make sure all atom matchers are initialized:
+ for (const sp<LogMatchingTracker>& tracker : newAtomMatchers) {
+ EXPECT_TRUE(tracker->mInitialized);
+ }
+ // Make sure preserved atom matchers are the same.
+ EXPECT_EQ(oldAtomMatchers[oldLogTrackerMap.at(simple1Id)],
+ newAtomMatchers[newLogTrackerMap.at(simple1Id)]);
+ EXPECT_EQ(oldAtomMatchers[oldLogTrackerMap.at(combination1Id)],
+ newAtomMatchers[newLogTrackerMap.at(combination1Id)]);
+ // Make sure replaced matchers are different.
+ EXPECT_NE(oldAtomMatchers[oldLogTrackerMap.at(simple2Id)],
+ newAtomMatchers[newLogTrackerMap.at(simple2Id)]);
+ EXPECT_NE(oldAtomMatchers[oldLogTrackerMap.at(combination2Id)],
+ newAtomMatchers[newLogTrackerMap.at(combination2Id)]);
+
+ // Validation, make sure the matchers have the proper ids. Could do more checks here.
+ EXPECT_EQ(newAtomMatchers[0]->getId(), combination3Id);
+ EXPECT_EQ(newAtomMatchers[1]->getId(), simple2Id);
+ EXPECT_EQ(newAtomMatchers[2]->getId(), combination2Id);
+ EXPECT_EQ(newAtomMatchers[3]->getId(), simple1Id);
+ EXPECT_EQ(newAtomMatchers[4]->getId(), simple4Id);
+ EXPECT_EQ(newAtomMatchers[5]->getId(), combination1Id);
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
diff --git a/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
new file mode 100644
index 000000000000..4e97eaf6f149
--- /dev/null
+++ b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
@@ -0,0 +1,708 @@
+// Copyright (C) 2020 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.
+
+#include "src/metrics/parsing_utils/metrics_manager_util.h"
+
+#include <gtest/gtest.h>
+#include <private/android_filesystem_config.h>
+#include <stdio.h>
+
+#include <set>
+#include <unordered_map>
+#include <vector>
+
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"
+#include "src/condition/ConditionTracker.h"
+#include "src/matchers/LogMatchingTracker.h"
+#include "src/metrics/CountMetricProducer.h"
+#include "src/metrics/GaugeMetricProducer.h"
+#include "src/metrics/MetricProducer.h"
+#include "src/metrics/ValueMetricProducer.h"
+#include "src/state/StateManager.h"
+#include "tests/metrics/metrics_test_helper.h"
+#include "tests/statsd_test_util.h"
+
+using namespace testing;
+using android::sp;
+using android::os::statsd::Predicate;
+using std::map;
+using std::set;
+using std::unordered_map;
+using std::vector;
+
+#ifdef __ANDROID__
+
+namespace android {
+namespace os {
+namespace statsd {
+
+namespace {
+const ConfigKey kConfigKey(0, 12345);
+const long kAlertId = 3;
+
+const long timeBaseSec = 1000;
+
+StatsdConfig buildGoodConfig() {
+ StatsdConfig config;
+ config.set_id(12345);
+
+ AtomMatcher* eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
+
+ SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->add_field_value_matcher()->set_field(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+ simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
+ 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
+
+ eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_IS_OFF"));
+
+ simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->add_field_value_matcher()->set_field(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+ simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/);
+
+ eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
+
+ AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_matcher(StringToId("SCREEN_IS_ON"));
+ combination->add_matcher(StringToId("SCREEN_IS_OFF"));
+
+ CountMetric* metric = config.add_count_metric();
+ metric->set_id(3);
+ metric->set_what(StringToId("SCREEN_IS_ON"));
+ metric->set_bucket(ONE_MINUTE);
+ metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/);
+ metric->mutable_dimensions_in_what()->add_child()->set_field(1);
+
+ config.add_no_report_metric(3);
+
+ auto alert = config.add_alert();
+ alert->set_id(kAlertId);
+ alert->set_metric_id(3);
+ alert->set_num_buckets(10);
+ alert->set_refractory_period_secs(100);
+ alert->set_trigger_if_sum_gt(100);
+ return config;
+}
+
+StatsdConfig buildCircleMatchers() {
+ StatsdConfig config;
+ config.set_id(12345);
+
+ AtomMatcher* eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
+
+ SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->add_field_value_matcher()->set_field(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+ simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
+ 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
+
+ eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
+
+ AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_matcher(StringToId("SCREEN_IS_ON"));
+ // Circle dependency
+ combination->add_matcher(StringToId("SCREEN_ON_OR_OFF"));
+
+ return config;
+}
+
+StatsdConfig buildAlertWithUnknownMetric() {
+ StatsdConfig config;
+ config.set_id(12345);
+
+ AtomMatcher* eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
+
+ CountMetric* metric = config.add_count_metric();
+ metric->set_id(3);
+ metric->set_what(StringToId("SCREEN_IS_ON"));
+ metric->set_bucket(ONE_MINUTE);
+ metric->mutable_dimensions_in_what()->set_field(2 /*SCREEN_STATE_CHANGE*/);
+ metric->mutable_dimensions_in_what()->add_child()->set_field(1);
+
+ auto alert = config.add_alert();
+ alert->set_id(3);
+ alert->set_metric_id(2);
+ alert->set_num_buckets(10);
+ alert->set_refractory_period_secs(100);
+ alert->set_trigger_if_sum_gt(100);
+ return config;
+}
+
+StatsdConfig buildMissingMatchers() {
+ StatsdConfig config;
+ config.set_id(12345);
+
+ AtomMatcher* eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
+
+ SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->add_field_value_matcher()->set_field(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+ simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
+ 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
+
+ eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_ON_OR_OFF"));
+
+ AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_matcher(StringToId("SCREEN_IS_ON"));
+ // undefined matcher
+ combination->add_matcher(StringToId("ABC"));
+
+ return config;
+}
+
+StatsdConfig buildMissingPredicate() {
+ StatsdConfig config;
+ config.set_id(12345);
+
+ CountMetric* metric = config.add_count_metric();
+ metric->set_id(3);
+ metric->set_what(StringToId("SCREEN_EVENT"));
+ metric->set_bucket(ONE_MINUTE);
+ metric->set_condition(StringToId("SOME_CONDITION"));
+
+ AtomMatcher* eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_EVENT"));
+
+ SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(2);
+
+ return config;
+}
+
+StatsdConfig buildDimensionMetricsWithMultiTags() {
+ StatsdConfig config;
+ config.set_id(12345);
+
+ AtomMatcher* eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("BATTERY_VERY_LOW"));
+ SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(2);
+
+ eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("BATTERY_VERY_VERY_LOW"));
+ simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(3);
+
+ eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("BATTERY_LOW"));
+
+ AtomMatcher_Combination* combination = eventMatcher->mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_matcher(StringToId("BATTERY_VERY_LOW"));
+ combination->add_matcher(StringToId("BATTERY_VERY_VERY_LOW"));
+
+ // Count process state changes, slice by uid, while SCREEN_IS_OFF
+ CountMetric* metric = config.add_count_metric();
+ metric->set_id(3);
+ metric->set_what(StringToId("BATTERY_LOW"));
+ metric->set_bucket(ONE_MINUTE);
+ // This case is interesting. We want to dimension across two atoms.
+ metric->mutable_dimensions_in_what()->add_child()->set_field(1);
+
+ auto alert = config.add_alert();
+ alert->set_id(kAlertId);
+ alert->set_metric_id(3);
+ alert->set_num_buckets(10);
+ alert->set_refractory_period_secs(100);
+ alert->set_trigger_if_sum_gt(100);
+ return config;
+}
+
+StatsdConfig buildCirclePredicates() {
+ StatsdConfig config;
+ config.set_id(12345);
+
+ AtomMatcher* eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_IS_ON"));
+
+ SimpleAtomMatcher* simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->add_field_value_matcher()->set_field(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+ simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
+ 2 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_ON*/);
+
+ eventMatcher = config.add_atom_matcher();
+ eventMatcher->set_id(StringToId("SCREEN_IS_OFF"));
+
+ simpleAtomMatcher = eventMatcher->mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(2 /*SCREEN_STATE_CHANGE*/);
+ simpleAtomMatcher->add_field_value_matcher()->set_field(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+ simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE__STATE_OFF*/);
+
+ auto condition = config.add_predicate();
+ condition->set_id(StringToId("SCREEN_IS_ON"));
+ SimplePredicate* simplePredicate = condition->mutable_simple_predicate();
+ simplePredicate->set_start(StringToId("SCREEN_IS_ON"));
+ simplePredicate->set_stop(StringToId("SCREEN_IS_OFF"));
+
+ condition = config.add_predicate();
+ condition->set_id(StringToId("SCREEN_IS_EITHER_ON_OFF"));
+
+ Predicate_Combination* combination = condition->mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_predicate(StringToId("SCREEN_IS_ON"));
+ combination->add_predicate(StringToId("SCREEN_IS_EITHER_ON_OFF"));
+
+ return config;
+}
+
+StatsdConfig buildConfigWithDifferentPredicates() {
+ StatsdConfig config;
+ config.set_id(12345);
+
+ auto pulledAtomMatcher =
+ CreateSimpleAtomMatcher("SUBSYSTEM_SLEEP", util::SUBSYSTEM_SLEEP_STATE);
+ *config.add_atom_matcher() = pulledAtomMatcher;
+ auto screenOnAtomMatcher = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = screenOnAtomMatcher;
+ auto screenOffAtomMatcher = CreateScreenTurnedOffAtomMatcher();
+ *config.add_atom_matcher() = screenOffAtomMatcher;
+ auto batteryNoneAtomMatcher = CreateBatteryStateNoneMatcher();
+ *config.add_atom_matcher() = batteryNoneAtomMatcher;
+ auto batteryUsbAtomMatcher = CreateBatteryStateUsbMatcher();
+ *config.add_atom_matcher() = batteryUsbAtomMatcher;
+
+ // Simple condition with InitialValue set to default (unknown).
+ auto screenOnUnknownPredicate = CreateScreenIsOnPredicate();
+ *config.add_predicate() = screenOnUnknownPredicate;
+
+ // Simple condition with InitialValue set to false.
+ auto screenOnFalsePredicate = config.add_predicate();
+ screenOnFalsePredicate->set_id(StringToId("ScreenIsOnInitialFalse"));
+ SimplePredicate* simpleScreenOnFalsePredicate =
+ screenOnFalsePredicate->mutable_simple_predicate();
+ simpleScreenOnFalsePredicate->set_start(screenOnAtomMatcher.id());
+ simpleScreenOnFalsePredicate->set_stop(screenOffAtomMatcher.id());
+ simpleScreenOnFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE);
+
+ // Simple condition with InitialValue set to false.
+ auto onBatteryFalsePredicate = config.add_predicate();
+ onBatteryFalsePredicate->set_id(StringToId("OnBatteryInitialFalse"));
+ SimplePredicate* simpleOnBatteryFalsePredicate =
+ onBatteryFalsePredicate->mutable_simple_predicate();
+ simpleOnBatteryFalsePredicate->set_start(batteryNoneAtomMatcher.id());
+ simpleOnBatteryFalsePredicate->set_stop(batteryUsbAtomMatcher.id());
+ simpleOnBatteryFalsePredicate->set_initial_value(SimplePredicate_InitialValue_FALSE);
+
+ // Combination condition with both simple condition InitialValues set to false.
+ auto screenOnFalseOnBatteryFalsePredicate = config.add_predicate();
+ screenOnFalseOnBatteryFalsePredicate->set_id(StringToId("ScreenOnFalseOnBatteryFalse"));
+ screenOnFalseOnBatteryFalsePredicate->mutable_combination()->set_operation(
+ LogicalOperation::AND);
+ addPredicateToPredicateCombination(*screenOnFalsePredicate,
+ screenOnFalseOnBatteryFalsePredicate);
+ addPredicateToPredicateCombination(*onBatteryFalsePredicate,
+ screenOnFalseOnBatteryFalsePredicate);
+
+ // Combination condition with one simple condition InitialValue set to unknown and one set to
+ // false.
+ auto screenOnUnknownOnBatteryFalsePredicate = config.add_predicate();
+ screenOnUnknownOnBatteryFalsePredicate->set_id(StringToId("ScreenOnUnknowneOnBatteryFalse"));
+ screenOnUnknownOnBatteryFalsePredicate->mutable_combination()->set_operation(
+ LogicalOperation::AND);
+ addPredicateToPredicateCombination(screenOnUnknownPredicate,
+ screenOnUnknownOnBatteryFalsePredicate);
+ addPredicateToPredicateCombination(*onBatteryFalsePredicate,
+ screenOnUnknownOnBatteryFalsePredicate);
+
+ // Simple condition metric with initial value false.
+ ValueMetric* metric1 = config.add_value_metric();
+ metric1->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialFalse"));
+ metric1->set_what(pulledAtomMatcher.id());
+ *metric1->mutable_value_field() =
+ CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
+ metric1->set_bucket(FIVE_MINUTES);
+ metric1->set_condition(screenOnFalsePredicate->id());
+
+ // Simple condition metric with initial value unknown.
+ ValueMetric* metric2 = config.add_value_metric();
+ metric2->set_id(StringToId("ValueSubsystemSleepWhileScreenOnInitialUnknown"));
+ metric2->set_what(pulledAtomMatcher.id());
+ *metric2->mutable_value_field() =
+ CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
+ metric2->set_bucket(FIVE_MINUTES);
+ metric2->set_condition(screenOnUnknownPredicate.id());
+
+ // Combination condition metric with initial values false and false.
+ ValueMetric* metric3 = config.add_value_metric();
+ metric3->set_id(StringToId("ValueSubsystemSleepWhileScreenOnFalseDeviceUnpluggedFalse"));
+ metric3->set_what(pulledAtomMatcher.id());
+ *metric3->mutable_value_field() =
+ CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
+ metric3->set_bucket(FIVE_MINUTES);
+ metric3->set_condition(screenOnFalseOnBatteryFalsePredicate->id());
+
+ // Combination condition metric with initial values unknown and false.
+ ValueMetric* metric4 = config.add_value_metric();
+ metric4->set_id(StringToId("ValueSubsystemSleepWhileScreenOnUnknownDeviceUnpluggedFalse"));
+ metric4->set_what(pulledAtomMatcher.id());
+ *metric4->mutable_value_field() =
+ CreateDimensions(util::SUBSYSTEM_SLEEP_STATE, {4 /* time sleeping field */});
+ metric4->set_bucket(FIVE_MINUTES);
+ metric4->set_condition(screenOnUnknownOnBatteryFalsePredicate->id());
+
+ return config;
+}
+} // anonymous namespace
+
+TEST(MetricsManagerTest, TestInitialConditions) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ StatsdConfig config = buildConfigWithDifferentPredicates();
+ set<int> allTagIds;
+ vector<sp<LogMatchingTracker>> allAtomMatchers;
+ unordered_map<int64_t, int> logTrackerMap;
+ vector<sp<ConditionTracker>> allConditionTrackers;
+ vector<sp<MetricProducer>> allMetricProducers;
+ std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
+ std::vector<sp<AlarmTracker>> allAlarmTrackers;
+ unordered_map<int, std::vector<int>> conditionToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToConditionMap;
+ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+ unordered_map<int64_t, int> alertTrackerMap;
+ vector<int> metricsWithActivation;
+ std::set<int64_t> noReportMetricIds;
+
+ EXPECT_TRUE(initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap,
+ allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
+ conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
+ metricsWithActivation, noReportMetricIds));
+ ASSERT_EQ(4u, allMetricProducers.size());
+ ASSERT_EQ(5u, allConditionTrackers.size());
+
+ ConditionKey queryKey;
+ vector<ConditionState> conditionCache(5, ConditionState::kNotEvaluated);
+
+ allConditionTrackers[3]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache);
+ allConditionTrackers[4]->isConditionMet(queryKey, allConditionTrackers, false, conditionCache);
+ EXPECT_EQ(ConditionState::kUnknown, conditionCache[0]);
+ EXPECT_EQ(ConditionState::kFalse, conditionCache[1]);
+ EXPECT_EQ(ConditionState::kFalse, conditionCache[2]);
+ EXPECT_EQ(ConditionState::kFalse, conditionCache[3]);
+ EXPECT_EQ(ConditionState::kUnknown, conditionCache[4]);
+
+ EXPECT_EQ(ConditionState::kFalse, allMetricProducers[0]->mCondition);
+ EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[1]->mCondition);
+ EXPECT_EQ(ConditionState::kFalse, allMetricProducers[2]->mCondition);
+ EXPECT_EQ(ConditionState::kUnknown, allMetricProducers[3]->mCondition);
+}
+
+TEST(MetricsManagerTest, TestGoodConfig) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ StatsdConfig config = buildGoodConfig();
+ set<int> allTagIds;
+ vector<sp<LogMatchingTracker>> allAtomMatchers;
+ unordered_map<int64_t, int> logTrackerMap;
+ vector<sp<ConditionTracker>> allConditionTrackers;
+ vector<sp<MetricProducer>> allMetricProducers;
+ std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
+ std::vector<sp<AlarmTracker>> allAlarmTrackers;
+ unordered_map<int, std::vector<int>> conditionToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToConditionMap;
+ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+ unordered_map<int64_t, int> alertTrackerMap;
+ vector<int> metricsWithActivation;
+ std::set<int64_t> noReportMetricIds;
+
+ EXPECT_TRUE(initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap,
+ allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
+ conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
+ metricsWithActivation, noReportMetricIds));
+ ASSERT_EQ(1u, allMetricProducers.size());
+ ASSERT_EQ(1u, allAnomalyTrackers.size());
+ ASSERT_EQ(1u, noReportMetricIds.size());
+ ASSERT_EQ(1u, alertTrackerMap.size());
+ EXPECT_NE(alertTrackerMap.find(kAlertId), alertTrackerMap.end());
+ EXPECT_EQ(alertTrackerMap.find(kAlertId)->second, 0);
+}
+
+TEST(MetricsManagerTest, TestDimensionMetricsWithMultiTags) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ StatsdConfig config = buildDimensionMetricsWithMultiTags();
+ set<int> allTagIds;
+ vector<sp<LogMatchingTracker>> allAtomMatchers;
+ unordered_map<int64_t, int> logTrackerMap;
+ vector<sp<ConditionTracker>> allConditionTrackers;
+ vector<sp<MetricProducer>> allMetricProducers;
+ std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
+ std::vector<sp<AlarmTracker>> allAlarmTrackers;
+ unordered_map<int, std::vector<int>> conditionToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToConditionMap;
+ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+ unordered_map<int64_t, int> alertTrackerMap;
+ vector<int> metricsWithActivation;
+ std::set<int64_t> noReportMetricIds;
+
+ EXPECT_FALSE(initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap,
+ allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
+ conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
+ metricsWithActivation, noReportMetricIds));
+}
+
+TEST(MetricsManagerTest, TestCircleLogMatcherDependency) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ StatsdConfig config = buildCircleMatchers();
+ set<int> allTagIds;
+ vector<sp<LogMatchingTracker>> allAtomMatchers;
+ unordered_map<int64_t, int> logTrackerMap;
+ vector<sp<ConditionTracker>> allConditionTrackers;
+ vector<sp<MetricProducer>> allMetricProducers;
+ std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
+ std::vector<sp<AlarmTracker>> allAlarmTrackers;
+ unordered_map<int, std::vector<int>> conditionToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToConditionMap;
+ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+ unordered_map<int64_t, int> alertTrackerMap;
+ vector<int> metricsWithActivation;
+ std::set<int64_t> noReportMetricIds;
+
+ EXPECT_FALSE(initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap,
+ allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
+ conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
+ metricsWithActivation, noReportMetricIds));
+}
+
+TEST(MetricsManagerTest, TestMissingMatchers) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ StatsdConfig config = buildMissingMatchers();
+ set<int> allTagIds;
+ vector<sp<LogMatchingTracker>> allAtomMatchers;
+ unordered_map<int64_t, int> logTrackerMap;
+ vector<sp<ConditionTracker>> allConditionTrackers;
+ vector<sp<MetricProducer>> allMetricProducers;
+ std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
+ std::vector<sp<AlarmTracker>> allAlarmTrackers;
+ unordered_map<int, std::vector<int>> conditionToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToConditionMap;
+ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+ unordered_map<int64_t, int> alertTrackerMap;
+ vector<int> metricsWithActivation;
+ std::set<int64_t> noReportMetricIds;
+ EXPECT_FALSE(initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap,
+ allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
+ conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
+ metricsWithActivation, noReportMetricIds));
+}
+
+TEST(MetricsManagerTest, TestMissingPredicate) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ StatsdConfig config = buildMissingPredicate();
+ set<int> allTagIds;
+ vector<sp<LogMatchingTracker>> allAtomMatchers;
+ unordered_map<int64_t, int> logTrackerMap;
+ vector<sp<ConditionTracker>> allConditionTrackers;
+ vector<sp<MetricProducer>> allMetricProducers;
+ std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
+ std::vector<sp<AlarmTracker>> allAlarmTrackers;
+ unordered_map<int, std::vector<int>> conditionToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToConditionMap;
+ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+ unordered_map<int64_t, int> alertTrackerMap;
+ vector<int> metricsWithActivation;
+ std::set<int64_t> noReportMetricIds;
+ EXPECT_FALSE(initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap,
+ allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
+ conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
+ metricsWithActivation, noReportMetricIds));
+}
+
+TEST(MetricsManagerTest, TestCirclePredicateDependency) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ StatsdConfig config = buildCirclePredicates();
+ set<int> allTagIds;
+ vector<sp<LogMatchingTracker>> allAtomMatchers;
+ unordered_map<int64_t, int> logTrackerMap;
+ vector<sp<ConditionTracker>> allConditionTrackers;
+ vector<sp<MetricProducer>> allMetricProducers;
+ std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
+ std::vector<sp<AlarmTracker>> allAlarmTrackers;
+ unordered_map<int, std::vector<int>> conditionToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToConditionMap;
+ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+ unordered_map<int64_t, int> alertTrackerMap;
+ vector<int> metricsWithActivation;
+ std::set<int64_t> noReportMetricIds;
+
+ EXPECT_FALSE(initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap,
+ allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
+ conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
+ metricsWithActivation, noReportMetricIds));
+}
+
+TEST(MetricsManagerTest, testAlertWithUnknownMetric) {
+ sp<UidMap> uidMap = new UidMap();
+ sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ sp<AlarmMonitor> periodicAlarmMonitor;
+ StatsdConfig config = buildAlertWithUnknownMetric();
+ set<int> allTagIds;
+ vector<sp<LogMatchingTracker>> allAtomMatchers;
+ unordered_map<int64_t, int> logTrackerMap;
+ vector<sp<ConditionTracker>> allConditionTrackers;
+ vector<sp<MetricProducer>> allMetricProducers;
+ std::vector<sp<AnomalyTracker>> allAnomalyTrackers;
+ std::vector<sp<AlarmTracker>> allAlarmTrackers;
+ unordered_map<int, std::vector<int>> conditionToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToMetricMap;
+ unordered_map<int, std::vector<int>> trackerToConditionMap;
+ unordered_map<int, std::vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, std::vector<int>> deactivationAtomTrackerToMetricMap;
+ unordered_map<int64_t, int> alertTrackerMap;
+ vector<int> metricsWithActivation;
+ std::set<int64_t> noReportMetricIds;
+
+ EXPECT_FALSE(initStatsdConfig(
+ kConfigKey, config, uidMap, pullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
+ timeBaseSec, timeBaseSec, allTagIds, allAtomMatchers, logTrackerMap,
+ allConditionTrackers, allMetricProducers, allAnomalyTrackers, allAlarmTrackers,
+ conditionToMetricMap, trackerToMetricMap, trackerToConditionMap,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap, alertTrackerMap,
+ metricsWithActivation, noReportMetricIds));
+}
+
+TEST(MetricsManagerTest, TestCreateLogTrackerInvalidMatcher) {
+ sp<UidMap> uidMap = new UidMap();
+ AtomMatcher matcher;
+ matcher.set_id(21);
+ EXPECT_EQ(createLogTracker(matcher, 0, uidMap), nullptr);
+}
+
+TEST(MetricsManagerTest, TestCreateLogTrackerSimple) {
+ int index = 1;
+ int64_t id = 123;
+ sp<UidMap> uidMap = new UidMap();
+ AtomMatcher matcher;
+ matcher.set_id(id);
+ SimpleAtomMatcher* simpleAtomMatcher = matcher.mutable_simple_atom_matcher();
+ simpleAtomMatcher->set_atom_id(util::SCREEN_STATE_CHANGED);
+ simpleAtomMatcher->add_field_value_matcher()->set_field(
+ 1 /*SCREEN_STATE_CHANGE__DISPLAY_STATE*/);
+ simpleAtomMatcher->mutable_field_value_matcher(0)->set_eq_int(
+ android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+
+ sp<LogMatchingTracker> tracker = createLogTracker(matcher, index, uidMap);
+ EXPECT_NE(tracker, nullptr);
+
+ EXPECT_TRUE(tracker->mInitialized);
+ EXPECT_EQ(tracker->getId(), id);
+ EXPECT_EQ(tracker->mIndex, index);
+ const set<int>& atomIds = tracker->getAtomIds();
+ ASSERT_EQ(atomIds.size(), 1);
+ EXPECT_EQ(atomIds.count(util::SCREEN_STATE_CHANGED), 1);
+}
+
+TEST(MetricsManagerTest, TestCreateLogTrackerCombination) {
+ int index = 1;
+ int64_t id = 123;
+ sp<UidMap> uidMap = new UidMap();
+ AtomMatcher matcher;
+ matcher.set_id(id);
+ AtomMatcher_Combination* combination = matcher.mutable_combination();
+ combination->set_operation(LogicalOperation::OR);
+ combination->add_matcher(123);
+ combination->add_matcher(223);
+
+ sp<LogMatchingTracker> tracker = createLogTracker(matcher, index, uidMap);
+ EXPECT_NE(tracker, nullptr);
+
+ // Combination matchers need to be initialized first.
+ EXPECT_FALSE(tracker->mInitialized);
+ EXPECT_EQ(tracker->getId(), id);
+ EXPECT_EQ(tracker->mIndex, index);
+ const set<int>& atomIds = tracker->getAtomIds();
+ ASSERT_EQ(atomIds.size(), 0);
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
+
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index cee83725d075..0be983f2a9b0 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -15,6 +15,8 @@
#include "statsd_test_util.h"
#include <aidl/android/util/StatsEventParcel.h>
+
+#include "matchers/SimpleLogMatchingTracker.h"
#include "stats_event.h"
using aidl::android::util::StatsEventParcel;
@@ -996,6 +998,20 @@ int64_t StringToId(const string& str) {
return static_cast<int64_t>(std::hash<std::string>()(str));
}
+sp<EventMatcherWizard> createEventMatcherWizard(
+ int tagId, int matcherIndex, const vector<FieldValueMatcher>& fieldValueMatchers) {
+ sp<UidMap> uidMap = new UidMap();
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ for (const FieldValueMatcher& fvm : fieldValueMatchers) {
+ *atomMatcher.add_field_value_matcher() = fvm;
+ }
+ uint64_t matcherHash = 0x12345678;
+ int64_t matcherId = 678;
+ return new EventMatcherWizard({new SimpleLogMatchingTracker(matcherId, matcherIndex,
+ matcherHash, atomMatcher, uidMap)});
+}
+
void ValidateWakelockAttributionUidAndTagDimension(const DimensionsValue& value, const int atomId,
const int uid, const string& tag) {
EXPECT_EQ(value.field(), atomId);
diff --git a/cmds/statsd/tests/statsd_test_util.h b/cmds/statsd/tests/statsd_test_util.h
index 3dcf4ecce054..1220019e2353 100644
--- a/cmds/statsd/tests/statsd_test_util.h
+++ b/cmds/statsd/tests/statsd_test_util.h
@@ -25,6 +25,7 @@
#include "src/StatsLogProcessor.h"
#include "src/hash.h"
#include "src/logd/LogEvent.h"
+#include "src/matchers/EventMatcherWizard.h"
#include "src/packages/UidMap.h"
#include "src/stats_log_util.h"
#include "stats_event.h"
@@ -335,6 +336,9 @@ void sortLogEventsByTimestamp(std::vector<std::unique_ptr<LogEvent>> *events);
int64_t StringToId(const string& str);
+sp<EventMatcherWizard> createEventMatcherWizard(
+ int tagId, int matcherIndex, const std::vector<FieldValueMatcher>& fieldValueMatchers = {});
+
void ValidateWakelockAttributionUidAndTagDimension(const DimensionsValue& value, const int atomId,
const int uid, const string& tag);
void ValidateUidDimension(const DimensionsValue& value, int node_idx, int atomId, int uid);
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index ab2f42b97e3b..f43bd2bd61b9 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -33629,6 +33629,35 @@ HSPLjava/math/BigInteger;-><init>([B)V
HSPLjava/math/BigInteger;->abs()Ljava/math/BigInteger;
HSPLjava/math/BigInteger;->add(Ljava/math/BigInteger;)Ljava/math/BigInteger;
HSPLjava/math/BigInteger;->bitLength()I
+#Temporary manual additions to avoid slowing tests down too much
+#Carefully positioned for clean merge
+HSPLjava/math/BigInteger;->add([IJ)[I
+HSPLjava/math/BigInteger;->add([I[I)[I
+HSPLjava/math/BigInteger;->subtract([IJ)[I
+HSPLjava/math/BigInteger;->subtract([I[I)[I
+HSPLjava/math/BigInteger;->jacobiSymbol(ILjava/math/BigInteger;)I
+HSPLjava/math/BigInteger;->lucasLehmerSequence(ILjava/math/BigInteger;Ljava/math/BigInteger;)Ljava/math/BigInteger;
+HSPLjava/math/BigInteger;->multiplyToLen([II[II[I)[I
+HSPLjava/math/MutableBigInteger;->add(Ljava/math/MutableBigInteger;)V
+HSPLjava/math/MutableBigInteger;->addShifted(Ljava/math/MutableBigInteger;)V
+HSPLjava/math/MutableBigInteger;->subtract(Ljava/math/MutableBigInteger;)V
+HSPLjava/math/MutableBigInteger;->difference(Ljava/math/MutableBigInteger;)V
+HSPLjava/math/MutableBigInteger;->divideKnuth(Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;Z)Ljava/math/MutableBigInteger;
+HSPLjava/math/MutableBigInteger;->divideMagnitude(Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;Z)Ljava/math/MutableBigInteger;
+HSPLjava/math/MutableBigInteger;->divideLongMagnitude(JLjava/math/MutableBigInteger;)Ljava/math/MutableBigInteger;
+HSPLjava/math/MutableBigInteger;->divideOneWord(ILjava/math/MutableBigInteger;)I
+HSPLjava/math/MutableBigInteger;->divadd([I[II)I
+HSPLjava/math/MutableBigInteger;->mulsub([I[IIII)I
+HSPLjava/math/MutableBigInteger;->mulsubBorrow([I[IIII)I
+HSPLjava/math/MutableBigInteger;->copyAndShift([III[III)V
+HSPLjava/math/MutableBigInteger;->multiply(Ljava/math/MutableBigInteger;Ljava/math/MutableBigInteger;)V
+HSPLjava/math/MutableBigInteger;->mul(ILjava/math/MutableBigInteger;)V
+HSPLjava/math/MutableBigInteger;->multiply(ILjava/math/MutableBigInteger;)V
+HSPLjava/math/MutableBigInteger;->primitiveRightShift(I)I
+HSPLjava/math/MutableBigInteger;->primitiveLeftShift(I)I
+HSPLjava/math/MutableBigInteger;->binaryGCD(Ljava/math/MutableBigInteger;)Ljava/math/MutableBigInteger;
+HSPLjava/math/MutableBigInteger;->binaryGCD(II)I
+#End of maual additions
HSPLjava/math/BigInteger;->compareTo(Ljava/math/BigInteger;)I
HSPLjava/math/BigInteger;->divide(Ljava/math/BigInteger;)Ljava/math/BigInteger;
HSPLjava/math/BigInteger;->divideAndRemainder(Ljava/math/BigInteger;)[Ljava/math/BigInteger;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 522b8cc5a46f..5c4951e23ea2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3827,6 +3827,12 @@ public class Activity extends ContextThemeWrapper
} catch (RemoteException e) {
finishAfterTransition();
}
+
+ // 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)) {
+ restoreAutofillSaveUi();
+ }
}
/**
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7cec717f96e0..d67b98620f37 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -424,9 +424,14 @@ public final class ActivityThread extends ClientTransactionHandler {
final String authority;
final int userId;
+ @GuardedBy("mLock")
+ ContentProviderHolder mHolder; // Temp holder to be used between notifier and waiter
+ Object mLock; // The lock to be used to get notified when the provider is ready
+
public ProviderKey(String authority, int userId) {
this.authority = authority;
this.userId = userId;
+ this.mLock = new Object();
}
@Override
@@ -440,7 +445,11 @@ public final class ActivityThread extends ClientTransactionHandler {
@Override
public int hashCode() {
- return ((authority != null) ? authority.hashCode() : 0) ^ userId;
+ return hashCode(authority, userId);
+ }
+
+ public static int hashCode(final String auth, final int userIdent) {
+ return ((auth != null) ? auth.hashCode() : 0) ^ userIdent;
}
}
@@ -461,9 +470,8 @@ public final class ActivityThread extends ClientTransactionHandler {
// Mitigation for b/74523247: Used to serialize calls to AM.getContentProvider().
// Note we never removes items from this map but that's okay because there are only so many
// users and so many authorities.
- // TODO Remove it once we move CPR.wait() from AMS to the client side.
- @GuardedBy("mGetProviderLocks")
- final ArrayMap<ProviderKey, Object> mGetProviderLocks = new ArrayMap<>();
+ @GuardedBy("mGetProviderKeys")
+ final SparseArray<ProviderKey> mGetProviderKeys = new SparseArray<>();
final ArrayMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners
= new ArrayMap<Activity, ArrayList<OnActivityPausedListener>>();
@@ -1756,6 +1764,16 @@ public final class ActivityThread extends ClientTransactionHandler {
ActivityThread.this, activityToken, actionId, arguments,
cancellationSignal, resultCallback));
}
+
+ @Override
+ public void notifyContentProviderPublishStatus(@NonNull ContentProviderHolder holder,
+ @NonNull String auth, int userId, boolean published) {
+ final ProviderKey key = getGetProviderKey(auth, userId);
+ synchronized (key.mLock) {
+ key.mHolder = holder;
+ key.mLock.notifyAll();
+ }
+ }
}
private @NonNull SafeCancellationTransport createSafeCancellationTransport(
@@ -6807,13 +6825,33 @@ public final class ActivityThread extends ClientTransactionHandler {
// provider since it might take a long time to run and it could also potentially
// be re-entrant in the case where the provider is in the same process.
ContentProviderHolder holder = null;
+ final ProviderKey key = getGetProviderKey(auth, userId);
try {
- synchronized (getGetProviderLock(auth, userId)) {
+ synchronized (key) {
holder = ActivityManager.getService().getContentProvider(
getApplicationThread(), c.getOpPackageName(), auth, userId, stable);
+ // If the returned holder is non-null but its provider is null and it's not
+ // local, we'll need to wait for the publishing of the provider.
+ if (holder != null && holder.provider == null && !holder.mLocal) {
+ synchronized (key.mLock) {
+ key.mLock.wait(ContentResolver.CONTENT_PROVIDER_READY_TIMEOUT_MILLIS);
+ holder = key.mHolder;
+ }
+ if (holder != null && holder.provider == null) {
+ // probably timed out
+ holder = null;
+ }
+ }
}
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
+ } catch (InterruptedException e) {
+ holder = null;
+ } finally {
+ // Clear the holder from the key since the key itself is never cleared.
+ synchronized (key.mLock) {
+ key.mHolder = null;
+ }
}
if (holder == null) {
if (UserManager.get(c).isUserUnlocked(userId)) {
@@ -6831,13 +6869,13 @@ public final class ActivityThread extends ClientTransactionHandler {
return holder.provider;
}
- private Object getGetProviderLock(String auth, int userId) {
- final ProviderKey key = new ProviderKey(auth, userId);
- synchronized (mGetProviderLocks) {
- Object lock = mGetProviderLocks.get(key);
+ private ProviderKey getGetProviderKey(String auth, int userId) {
+ final int key = ProviderKey.hashCode(auth, userId);
+ synchronized (mGetProviderKeys) {
+ ProviderKey lock = mGetProviderKeys.get(key);
if (lock == null) {
- lock = key;
- mGetProviderLocks.put(key, lock);
+ lock = new ProviderKey(auth, userId);
+ mGetProviderKeys.put(key, lock);
}
return lock;
}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index dedd8705ef55..676c6c01d349 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -684,8 +684,7 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public int checkPermission(String permName, String pkgName) {
- return PermissionManager
- .checkPackageNamePermission(permName, pkgName, getUserId());
+ return PermissionManager.checkPackageNamePermission(permName, pkgName, getUserId());
}
@Override
diff --git a/core/java/android/app/ContentProviderHolder.java b/core/java/android/app/ContentProviderHolder.java
index 3d745831ce1c..e330a30de7b0 100644
--- a/core/java/android/app/ContentProviderHolder.java
+++ b/core/java/android/app/ContentProviderHolder.java
@@ -39,6 +39,11 @@ public class ContentProviderHolder implements Parcelable {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public boolean noReleaseNeeded;
+ /**
+ * Whether the provider here is a local provider or not.
+ */
+ public boolean mLocal;
+
@UnsupportedAppUsage
public ContentProviderHolder(ProviderInfo _info) {
info = _info;
@@ -59,6 +64,7 @@ public class ContentProviderHolder implements Parcelable {
}
dest.writeStrongBinder(connection);
dest.writeInt(noReleaseNeeded ? 1 : 0);
+ dest.writeInt(mLocal ? 1 : 0);
}
public static final @android.annotation.NonNull Parcelable.Creator<ContentProviderHolder> CREATOR
@@ -81,5 +87,6 @@ public class ContentProviderHolder implements Parcelable {
source.readStrongBinder());
connection = source.readStrongBinder();
noReleaseNeeded = source.readInt() != 0;
+ mLocal = source.readInt() != 0;
}
-} \ No newline at end of file
+}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 93dfc79109a6..f37ca61ba69f 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -461,7 +461,7 @@ interface IActivityManager {
@UnsupportedAppUsage
Rect getTaskBounds(int taskId);
@UnsupportedAppUsage
- boolean setProcessMemoryTrimLevel(in String process, int uid, int level);
+ boolean setProcessMemoryTrimLevel(in String process, int userId, int level);
// Start of L transactions
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 24da50481df3..dc9918ade9c2 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -16,6 +16,7 @@
package android.app;
+import android.app.ContentProviderHolder;
import android.app.IInstrumentationWatcher;
import android.app.IUiAutomationConnection;
import android.app.ProfilerInfo;
@@ -147,4 +148,6 @@ oneway interface IApplicationThread {
void performDirectAction(IBinder activityToken, String actionId,
in Bundle arguments, in RemoteCallback cancellationCallback,
in RemoteCallback resultCallback);
+ void notifyContentProviderPublishStatus(in ContentProviderHolder holder, String auth,
+ int userId, boolean published);
}
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl
index 8c3180b400ef..4c9e400681ee 100644
--- a/core/java/android/app/IUiAutomationConnection.aidl
+++ b/core/java/android/app/IUiAutomationConnection.aidl
@@ -39,7 +39,7 @@ interface IUiAutomationConnection {
boolean injectInputEvent(in InputEvent event, boolean sync);
void syncInputTransactions();
boolean setRotation(int rotation);
- Bitmap takeScreenshot(in Rect crop, int rotation);
+ Bitmap takeScreenshot(in Rect crop);
boolean clearWindowContentFrameStats(int windowId);
WindowContentFrameStats getWindowContentFrameStats(int windowId);
void clearWindowAnimationFrameStats();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 68e65612971c..6f3e89229e4c 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1492,6 +1492,7 @@ public class Notification implements Parcelable
private boolean mAllowGeneratedReplies = true;
private final @SemanticAction int mSemanticAction;
private final boolean mIsContextual;
+ private boolean mAuthenticationRequired;
/**
* Small icon representing the action.
@@ -1528,6 +1529,7 @@ public class Notification implements Parcelable
mAllowGeneratedReplies = in.readInt() == 1;
mSemanticAction = in.readInt();
mIsContextual = in.readInt() == 1;
+ mAuthenticationRequired = in.readInt() == 1;
}
/**
@@ -1536,13 +1538,14 @@ public class Notification implements Parcelable
@Deprecated
public Action(int icon, CharSequence title, PendingIntent intent) {
this(Icon.createWithResource("", icon), title, intent, new Bundle(), null, true,
- SEMANTIC_ACTION_NONE, false /* isContextual */);
+ SEMANTIC_ACTION_NONE, false /* isContextual */, false /* requireAuth */);
}
/** Keep in sync with {@link Notification.Action.Builder#Builder(Action)}! */
private Action(Icon icon, CharSequence title, PendingIntent intent, Bundle extras,
RemoteInput[] remoteInputs, boolean allowGeneratedReplies,
- @SemanticAction int semanticAction, boolean isContextual) {
+ @SemanticAction int semanticAction, boolean isContextual,
+ boolean requireAuth) {
this.mIcon = icon;
if (icon != null && icon.getType() == Icon.TYPE_RESOURCE) {
this.icon = icon.getResId();
@@ -1554,6 +1557,7 @@ public class Notification implements Parcelable
this.mAllowGeneratedReplies = allowGeneratedReplies;
this.mSemanticAction = semanticAction;
this.mIsContextual = isContextual;
+ this.mAuthenticationRequired = requireAuth;
}
/**
@@ -1624,6 +1628,17 @@ public class Notification implements Parcelable
}
/**
+ * Returns whether the OS should only send this action's {@link PendingIntent} on an
+ * unlocked device.
+ *
+ * If the device is locked when the action is invoked, the OS should show the keyguard and
+ * require successful authentication before invoking the intent.
+ */
+ public boolean isAuthenticationRequired() {
+ return mAuthenticationRequired;
+ }
+
+ /**
* Builder class for {@link Action} objects.
*/
public static final class Builder {
@@ -1635,6 +1650,7 @@ public class Notification implements Parcelable
@Nullable private ArrayList<RemoteInput> mRemoteInputs;
private @SemanticAction int mSemanticAction;
private boolean mIsContextual;
+ private boolean mAuthenticationRequired;
/**
* Construct a new builder for {@link Action} object.
@@ -1654,7 +1670,7 @@ public class Notification implements Parcelable
* @param intent the {@link PendingIntent} to fire when users trigger this action
*/
public Builder(Icon icon, CharSequence title, PendingIntent intent) {
- this(icon, title, intent, new Bundle(), null, true, SEMANTIC_ACTION_NONE);
+ this(icon, title, intent, new Bundle(), null, true, SEMANTIC_ACTION_NONE, false);
}
/**
@@ -1665,23 +1681,25 @@ public class Notification implements Parcelable
public Builder(Action action) {
this(action.getIcon(), action.title, action.actionIntent,
new Bundle(action.mExtras), action.getRemoteInputs(),
- action.getAllowGeneratedReplies(), action.getSemanticAction());
+ action.getAllowGeneratedReplies(), action.getSemanticAction(),
+ action.isAuthenticationRequired());
}
private Builder(@Nullable Icon icon, @Nullable CharSequence title,
@Nullable PendingIntent intent, @NonNull Bundle extras,
@Nullable RemoteInput[] remoteInputs, boolean allowGeneratedReplies,
- @SemanticAction int semanticAction) {
+ @SemanticAction int semanticAction, boolean authRequired) {
mIcon = icon;
mTitle = title;
mIntent = intent;
mExtras = extras;
if (remoteInputs != null) {
- mRemoteInputs = new ArrayList<RemoteInput>(remoteInputs.length);
+ mRemoteInputs = new ArrayList<>(remoteInputs.length);
Collections.addAll(mRemoteInputs, remoteInputs);
}
mAllowGeneratedReplies = allowGeneratedReplies;
mSemanticAction = semanticAction;
+ mAuthenticationRequired = authRequired;
}
/**
@@ -1776,6 +1794,21 @@ public class Notification implements Parcelable
}
/**
+ * Sets whether the OS should only send this action's {@link PendingIntent} on an
+ * unlocked device.
+ *
+ * If this is true and the device is locked when the action is invoked, the OS will
+ * show the keyguard and require successful authentication before invoking the intent.
+ * If this is false and the device is locked, the OS will decide whether authentication
+ * should be required.
+ */
+ @NonNull
+ public Builder setAuthenticationRequired(boolean authenticationRequired) {
+ mAuthenticationRequired = authenticationRequired;
+ return this;
+ }
+
+ /**
* Throws an NPE if we are building a contextual action missing one of the fields
* necessary to display the action.
*/
@@ -1827,7 +1860,8 @@ public class Notification implements Parcelable
RemoteInput[] textInputsArr = textInputs.isEmpty()
? null : textInputs.toArray(new RemoteInput[textInputs.size()]);
return new Action(mIcon, mTitle, mIntent, mExtras, textInputsArr,
- mAllowGeneratedReplies, mSemanticAction, mIsContextual);
+ mAllowGeneratedReplies, mSemanticAction, mIsContextual,
+ mAuthenticationRequired);
}
}
@@ -1841,7 +1875,8 @@ public class Notification implements Parcelable
getRemoteInputs(),
getAllowGeneratedReplies(),
getSemanticAction(),
- isContextual());
+ isContextual(),
+ isAuthenticationRequired());
}
@Override
@@ -1870,6 +1905,7 @@ public class Notification implements Parcelable
out.writeInt(mAllowGeneratedReplies ? 1 : 0);
out.writeInt(mSemanticAction);
out.writeInt(mIsContextual ? 1 : 0);
+ out.writeInt(mAuthenticationRequired ? 1 : 0);
}
public static final @android.annotation.NonNull Parcelable.Creator<Action> CREATOR =
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index e0951bf3f4d2..109205fadf18 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -903,7 +903,7 @@ public final class UiAutomation {
try {
// Calling out without a lock held.
screenShot = mUiAutomationConnection.takeScreenshot(
- new Rect(0, 0, displaySize.x, displaySize.y), rotation);
+ new Rect(0, 0, displaySize.x, displaySize.y));
if (screenShot == null) {
return null;
}
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index ce51dba76780..70d520176ca1 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -180,7 +180,7 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
}
@Override
- public Bitmap takeScreenshot(Rect crop, int rotation) {
+ public Bitmap takeScreenshot(Rect crop) {
synchronized (mLock) {
throwIfCalledByNotTrustedUidLocked();
throwIfShutdownLocked();
@@ -190,7 +190,15 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
try {
int width = crop.width();
int height = crop.height();
- return SurfaceControl.screenshot(crop, width, height, rotation);
+ final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
+ final SurfaceControl.DisplayCaptureArgs captureArgs =
+ new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
+ .setSourceCrop(crop)
+ .setSize(width, height)
+ .build();
+ final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
+ SurfaceControl.captureDisplay(captureArgs);
+ return screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 16ddcd1d0ea3..056cfc7c28f1 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -402,7 +402,7 @@ public abstract class BackupAgent extends ContextWrapper {
*/
public void onFullBackup(FullBackupDataOutput data) throws IOException {
FullBackup.BackupScheme backupScheme = FullBackup.getBackupScheme(this);
- if (!backupScheme.isFullBackupContentEnabled()) {
+ if (!isDeviceToDeviceMigration() && !backupScheme.isFullBackupContentEnabled()) {
return;
}
@@ -430,24 +430,18 @@ public abstract class BackupAgent extends ContextWrapper {
final Context ceContext = createCredentialProtectedStorageContext();
final String rootDir = ceContext.getDataDir().getCanonicalPath();
final String filesDir = ceContext.getFilesDir().getCanonicalPath();
- final String noBackupDir = ceContext.getNoBackupFilesDir().getCanonicalPath();
final String databaseDir = ceContext.getDatabasePath("foo").getParentFile()
.getCanonicalPath();
final String sharedPrefsDir = ceContext.getSharedPreferencesPath("foo").getParentFile()
.getCanonicalPath();
- final String cacheDir = ceContext.getCacheDir().getCanonicalPath();
- final String codeCacheDir = ceContext.getCodeCacheDir().getCanonicalPath();
final Context deContext = createDeviceProtectedStorageContext();
final String deviceRootDir = deContext.getDataDir().getCanonicalPath();
final String deviceFilesDir = deContext.getFilesDir().getCanonicalPath();
- final String deviceNoBackupDir = deContext.getNoBackupFilesDir().getCanonicalPath();
final String deviceDatabaseDir = deContext.getDatabasePath("foo").getParentFile()
.getCanonicalPath();
final String deviceSharedPrefsDir = deContext.getSharedPreferencesPath("foo")
.getParentFile().getCanonicalPath();
- final String deviceCacheDir = deContext.getCacheDir().getCanonicalPath();
- final String deviceCodeCacheDir = deContext.getCodeCacheDir().getCanonicalPath();
final String libDir = (appInfo.nativeLibraryDir != null)
? new File(appInfo.nativeLibraryDir).getCanonicalPath()
@@ -460,33 +454,36 @@ public abstract class BackupAgent extends ContextWrapper {
// Add the directories we always exclude.
traversalExcludeSet.add(filesDir);
- traversalExcludeSet.add(noBackupDir);
traversalExcludeSet.add(databaseDir);
traversalExcludeSet.add(sharedPrefsDir);
- traversalExcludeSet.add(cacheDir);
- traversalExcludeSet.add(codeCacheDir);
traversalExcludeSet.add(deviceFilesDir);
- traversalExcludeSet.add(deviceNoBackupDir);
traversalExcludeSet.add(deviceDatabaseDir);
traversalExcludeSet.add(deviceSharedPrefsDir);
- traversalExcludeSet.add(deviceCacheDir);
- traversalExcludeSet.add(deviceCodeCacheDir);
if (libDir != null) {
traversalExcludeSet.add(libDir);
}
+ Set<String> extraExcludedDirs = getExtraExcludeDirsIfAny(ceContext);
+ Set<String> extraExcludedDeviceDirs = getExtraExcludeDirsIfAny(deContext);
+ traversalExcludeSet.addAll(extraExcludedDirs);
+ traversalExcludeSet.addAll(extraExcludedDeviceDirs);
+
// Root dir first.
applyXmlFiltersAndDoFullBackupForDomain(
packageName, FullBackup.ROOT_TREE_TOKEN, manifestIncludeMap,
manifestExcludeSet, traversalExcludeSet, data);
traversalExcludeSet.add(rootDir);
+ // Exclude the extra directories anyway, since we've already covered them if it was needed.
+ traversalExcludeSet.addAll(extraExcludedDirs);
applyXmlFiltersAndDoFullBackupForDomain(
packageName, FullBackup.DEVICE_ROOT_TREE_TOKEN, manifestIncludeMap,
manifestExcludeSet, traversalExcludeSet, data);
traversalExcludeSet.add(deviceRootDir);
+ // Exclude the extra directories anyway, since we've already covered them if it was needed.
+ traversalExcludeSet.addAll(extraExcludedDeviceDirs);
// Data dir next.
traversalExcludeSet.remove(filesDir);
@@ -545,11 +542,28 @@ public abstract class BackupAgent extends ContextWrapper {
}
}
+ private Set<String> getExtraExcludeDirsIfAny(Context context) throws IOException {
+ if (isDeviceToDeviceMigration()) {
+ return Collections.emptySet();
+ }
+
+ // If this is not a migration, also exclude no-backup and cache dirs.
+ Set<String> excludedDirs = new HashSet<>();
+ excludedDirs.add(context.getCacheDir().getCanonicalPath());
+ excludedDirs.add(context.getCodeCacheDir().getCanonicalPath());
+ excludedDirs.add(context.getNoBackupFilesDir().getCanonicalPath());
+ return Collections.unmodifiableSet(excludedDirs);
+ }
+
+ private boolean isDeviceToDeviceMigration() {
+ return mOperationType == OperationType.MIGRATION;
+ }
+
/** @hide */
@VisibleForTesting
public IncludeExcludeRules getIncludeExcludeRules(FullBackup.BackupScheme backupScheme)
throws IOException, XmlPullParserException {
- if (mOperationType == OperationType.MIGRATION) {
+ if (isDeviceToDeviceMigration()) {
return IncludeExcludeRules.emptyRules();
}
@@ -892,6 +906,11 @@ public abstract class BackupAgent extends ContextWrapper {
}
private boolean isFileEligibleForRestore(File destination) throws IOException {
+ if (isDeviceToDeviceMigration()) {
+ // Everything is eligible for device-to-device migration.
+ return true;
+ }
+
FullBackup.BackupScheme bs = FullBackup.getBackupScheme(this);
if (!bs.isFullBackupContentEnabled()) {
if (Log.isLoggable(FullBackup.TAG_XML_PARSER, Log.VERBOSE)) {
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index bd1eea51f8af..cef6ab094177 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -155,10 +155,6 @@ public abstract class SliceProvider extends ContentProvider {
/**
* @hide
*/
- public static final String EXTRA_PROVIDER_PKG = "provider_pkg";
- /**
- * @hide
- */
public static final String EXTRA_RESULT = "result";
private static final boolean DEBUG = false;
@@ -519,7 +515,6 @@ public abstract class SliceProvider extends ContentProvider {
com.android.internal.R.string.config_slicePermissionComponent)));
intent.putExtra(EXTRA_BIND_URI, sliceUri);
intent.putExtra(EXTRA_PKG, callingPackage);
- intent.putExtra(EXTRA_PROVIDER_PKG, context.getPackageName());
// Unique pending intent.
intent.setData(sliceUri.buildUpon().appendQueryParameter("package", callingPackage)
.build());
diff --git a/core/java/android/app/timezonedetector/TimeZoneCapabilities.java b/core/java/android/app/timezonedetector/TimeZoneCapabilities.java
index 236b0064763e..cc0af3f97e49 100644
--- a/core/java/android/app/timezonedetector/TimeZoneCapabilities.java
+++ b/core/java/android/app/timezonedetector/TimeZoneCapabilities.java
@@ -91,11 +91,13 @@ public final class TimeZoneCapabilities implements Parcelable {
private final @UserIdInt int mUserId;
private final @CapabilityState int mConfigureAutoDetectionEnabled;
+ private final @CapabilityState int mConfigureGeoDetectionEnabled;
private final @CapabilityState int mSuggestManualTimeZone;
private TimeZoneCapabilities(@NonNull Builder builder) {
this.mUserId = builder.mUserId;
this.mConfigureAutoDetectionEnabled = builder.mConfigureAutoDetectionEnabled;
+ this.mConfigureGeoDetectionEnabled = builder.mConfigureGeoDetectionEnabled;
this.mSuggestManualTimeZone = builder.mSuggestManualTimeZone;
}
@@ -103,6 +105,7 @@ public final class TimeZoneCapabilities implements Parcelable {
private static TimeZoneCapabilities createFromParcel(Parcel in) {
return new TimeZoneCapabilities.Builder(in.readInt())
.setConfigureAutoDetectionEnabled(in.readInt())
+ .setConfigureGeoDetectionEnabled(in.readInt())
.setSuggestManualTimeZone(in.readInt())
.build();
}
@@ -111,6 +114,7 @@ public final class TimeZoneCapabilities implements Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mUserId);
dest.writeInt(mConfigureAutoDetectionEnabled);
+ dest.writeInt(mConfigureGeoDetectionEnabled);
dest.writeInt(mSuggestManualTimeZone);
}
@@ -120,8 +124,8 @@ public final class TimeZoneCapabilities implements Parcelable {
}
/**
- * Returns the user's capability state for controlling automatic time zone detection via
- * {@link TimeZoneDetector#updateConfiguration(TimeZoneConfiguration)} and {@link
+ * Returns the user's capability state for controlling whether automatic time zone detection is
+ * enabled via {@link TimeZoneDetector#updateConfiguration(TimeZoneConfiguration)} and {@link
* TimeZoneConfiguration#isAutoDetectionEnabled()}.
*/
@CapabilityState
@@ -130,6 +134,16 @@ public final class TimeZoneCapabilities implements Parcelable {
}
/**
+ * Returns the user's capability state for controlling whether geolocation can be used to detect
+ * time zone via {@link TimeZoneDetector#updateConfiguration(TimeZoneConfiguration)} and {@link
+ * TimeZoneConfiguration#isGeoDetectionEnabled()}.
+ */
+ @CapabilityState
+ public int getConfigureGeoDetectionEnabled() {
+ return mConfigureGeoDetectionEnabled;
+ }
+
+ /**
* Returns the user's capability state for manually setting the time zone on a device via
* {@link TimeZoneDetector#suggestManualTimeZone(ManualTimeZoneSuggestion)}.
*
@@ -157,12 +171,16 @@ public final class TimeZoneCapabilities implements Parcelable {
TimeZoneCapabilities that = (TimeZoneCapabilities) o;
return mUserId == that.mUserId
&& mConfigureAutoDetectionEnabled == that.mConfigureAutoDetectionEnabled
+ && mConfigureGeoDetectionEnabled == that.mConfigureGeoDetectionEnabled
&& mSuggestManualTimeZone == that.mSuggestManualTimeZone;
}
@Override
public int hashCode() {
- return Objects.hash(mUserId, mConfigureAutoDetectionEnabled, mSuggestManualTimeZone);
+ return Objects.hash(mUserId,
+ mConfigureAutoDetectionEnabled,
+ mConfigureGeoDetectionEnabled,
+ mSuggestManualTimeZone);
}
@Override
@@ -170,6 +188,7 @@ public final class TimeZoneCapabilities implements Parcelable {
return "TimeZoneDetectorCapabilities{"
+ "mUserId=" + mUserId
+ ", mConfigureAutomaticDetectionEnabled=" + mConfigureAutoDetectionEnabled
+ + ", mConfigureGeoDetectionEnabled=" + mConfigureGeoDetectionEnabled
+ ", mSuggestManualTimeZone=" + mSuggestManualTimeZone
+ '}';
}
@@ -179,6 +198,7 @@ public final class TimeZoneCapabilities implements Parcelable {
private final @UserIdInt int mUserId;
private @CapabilityState int mConfigureAutoDetectionEnabled;
+ private @CapabilityState int mConfigureGeoDetectionEnabled;
private @CapabilityState int mSuggestManualTimeZone;
/**
@@ -194,6 +214,12 @@ public final class TimeZoneCapabilities implements Parcelable {
return this;
}
+ /** Sets the state for the geolocation time zone detection enabled config. */
+ public Builder setConfigureGeoDetectionEnabled(@CapabilityState int value) {
+ this.mConfigureGeoDetectionEnabled = value;
+ return this;
+ }
+
/** Sets the state for the suggestManualTimeZone action. */
public Builder setSuggestManualTimeZone(@CapabilityState int value) {
this.mSuggestManualTimeZone = value;
@@ -204,6 +230,7 @@ public final class TimeZoneCapabilities implements Parcelable {
@NonNull
public TimeZoneCapabilities build() {
verifyCapabilitySet(mConfigureAutoDetectionEnabled, "configureAutoDetectionEnabled");
+ verifyCapabilitySet(mConfigureGeoDetectionEnabled, "configureGeoDetectionEnabled");
verifyCapabilitySet(mSuggestManualTimeZone, "suggestManualTimeZone");
return new TimeZoneCapabilities(this);
}
diff --git a/core/java/android/app/timezonedetector/TimeZoneConfiguration.java b/core/java/android/app/timezonedetector/TimeZoneConfiguration.java
index 047d3493d5dd..6f84ee22a985 100644
--- a/core/java/android/app/timezonedetector/TimeZoneConfiguration.java
+++ b/core/java/android/app/timezonedetector/TimeZoneConfiguration.java
@@ -67,6 +67,10 @@ public final class TimeZoneConfiguration implements Parcelable {
@Property
public static final String PROPERTY_AUTO_DETECTION_ENABLED = "autoDetectionEnabled";
+ /** See {@link TimeZoneConfiguration#isGeoDetectionEnabled()} for details. */
+ @Property
+ public static final String PROPERTY_GEO_DETECTION_ENABLED = "geoDetectionEnabled";
+
private final Bundle mBundle;
private TimeZoneConfiguration(Builder builder) {
@@ -86,7 +90,8 @@ public final class TimeZoneConfiguration implements Parcelable {
/** Returns {@code true} if all known properties are set. */
public boolean isComplete() {
- return hasProperty(PROPERTY_AUTO_DETECTION_ENABLED);
+ return hasProperty(PROPERTY_AUTO_DETECTION_ENABLED)
+ && hasProperty(PROPERTY_GEO_DETECTION_ENABLED);
}
/** Returns true if the specified property is set. */
@@ -108,6 +113,28 @@ public final class TimeZoneConfiguration implements Parcelable {
return mBundle.getBoolean(PROPERTY_AUTO_DETECTION_ENABLED);
}
+ /**
+ * Returns the value of the {@link #PROPERTY_GEO_DETECTION_ENABLED} property. This
+ * controls whether a device can use location to determine time zone. Only used when
+ * {@link #isAutoDetectionEnabled()} is true.
+ *
+ * @throws IllegalStateException if the field has not been set
+ */
+ public boolean isGeoDetectionEnabled() {
+ if (!mBundle.containsKey(PROPERTY_GEO_DETECTION_ENABLED)) {
+ throw new IllegalStateException(PROPERTY_GEO_DETECTION_ENABLED + " is not set");
+ }
+ return mBundle.getBoolean(PROPERTY_GEO_DETECTION_ENABLED);
+ }
+
+ /**
+ * Convenience method to merge this with another. The argument configuration properties have
+ * precedence.
+ */
+ public TimeZoneConfiguration with(TimeZoneConfiguration other) {
+ return new Builder(this).mergeProperties(other).build();
+ }
+
@Override
public int describeContents() {
return 0;
@@ -174,6 +201,12 @@ public final class TimeZoneConfiguration implements Parcelable {
return this;
}
+ /** Sets the desired state of the geolocation time zone detection enabled property. */
+ public Builder setGeoDetectionEnabled(boolean enabled) {
+ this.mBundle.putBoolean(PROPERTY_GEO_DETECTION_ENABLED, enabled);
+ return this;
+ }
+
/** Returns the {@link TimeZoneConfiguration}. */
@NonNull
public TimeZoneConfiguration build() {
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 3522b1b8aff5..0e6a0637d801 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -199,7 +199,7 @@ public final class UsageEvents implements Parcelable {
public static final int NOTIFICATION_INTERRUPTION = 12;
/**
- * A Slice was pinned by the default launcher or the default assistant.
+ * A Slice was pinned by the default assistant.
* @hide
*/
@SystemApi
diff --git a/core/java/android/content/LocusId.java b/core/java/android/content/LocusId.java
index 283cea00b192..98e71f07407e 100644
--- a/core/java/android/content/LocusId.java
+++ b/core/java/android/content/LocusId.java
@@ -33,7 +33,7 @@ import java.io.PrintWriter;
* by the Android System to correlate state between different subsystems such as content capture,
* shortcuts, and notifications.
*
- * <p>For example, if your app provides an activiy representing a chat between 2 users
+ * <p>For example, if your app provides an activity representing a chat between 2 users
* (say {@code A} and {@code B}, this chat state could be represented by:
*
* <pre><code>
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 7234eb1d81cd..cd26079a7bac 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -503,6 +503,10 @@ public class NetworkTemplate implements Parcelable {
for (final int ratType : ratTypes) {
collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(ratType));
}
+ // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and
+ // it is not in TelephonyManager#NETWORK_TYPE_* constants.
+ // See {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}.
+ collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(NETWORK_TYPE_5G_NSA));
// Ensure that unknown type is returned.
collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN);
return toIntArray(collapsedRatTypes);
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 1050c7f8b4f4..8e865e7ab313 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1012,10 +1012,16 @@ public class Build {
/**
* Q.
- * <p>
- * <em>Why? Why, to give you a taste of your future, a preview of things
- * to come. Con permiso, Capitan. The hall is rented, the orchestra
- * engaged. It's now time to see if you can dance.</em>
+ *
+ * <p>Applications targeting this or a later release will get these new changes in behavior.
+ * For more information about this release, see the
+ * <a href="/about/versions/10">Android 10 overview</a>.</p>
+ * <ul>
+ * <li><a href="/about/versions/10/behavior-changes-all">Behavior changes: all apps</a></li>
+ * <li><a href="/about/versions/10/behavior-changes-10">Behavior changes: apps targeting API
+ * 29+</a></li>
+ * </ul>
+ *
*/
public static final int Q = 29;
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 0cce19222d27..8f8d451bbe8e 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -287,8 +287,8 @@ interface INetworkManagementService
/**
* Control network activity of a UID over interfaces with a quota limit.
*/
- void setUidMeteredNetworkBlacklist(int uid, boolean enable);
- void setUidMeteredNetworkWhitelist(int uid, boolean enable);
+ void setUidMeteredNetworkDenylist(int uid, boolean enable);
+ void setUidMeteredNetworkAllowlist(int uid, boolean enable);
boolean setDataSaverModeEnabled(boolean enable);
void setUidCleartextNetworkPolicy(int uid, int policy);
diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java
index 3d3759e695e0..f14f66b07630 100644
--- a/core/java/android/os/Parcelable.java
+++ b/core/java/android/os/Parcelable.java
@@ -161,6 +161,7 @@ public interface Parcelable {
* @return true if this parcelable is stable.
* @hide
*/
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
default @Stability int getStability() {
return PARCELABLE_STABILITY_LOCAL;
}
diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java
index fd68c2b9b5fd..26f3af0c68bb 100644
--- a/core/java/android/os/SystemClock.java
+++ b/core/java/android/os/SystemClock.java
@@ -178,6 +178,15 @@ public final class SystemClock {
native public static long uptimeMillis();
/**
+ * Returns nanoseconds since boot, not counting time spent in deep sleep.
+ *
+ * @return nanoseconds of non-sleep uptime since boot.
+ * @hide
+ */
+ @CriticalNative
+ public static native long uptimeNanos();
+
+ /**
* Return {@link Clock} that starts at system boot, not counting time spent
* in deep sleep.
*
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index 8ad35e7eb37d..e2e61406ba95 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -35,6 +35,8 @@ import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.app.Service;
import android.app.admin.DevicePolicyManager.PermissionGrantState;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.Disabled;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -83,6 +85,15 @@ public abstract class PermissionControllerService extends Service {
public static final String SERVICE_INTERFACE = "android.permission.PermissionControllerService";
/**
+ * A ChangeId indicating that this device supports camera and mic indicators. Will be "false"
+ * if present, because the CompatChanges#isChangeEnabled method returns true if the change id
+ * is not present.
+ */
+ @ChangeId
+ @Disabled
+ private static final long CAMERA_MIC_INDICATORS_NOT_PRESENT = 162547999L;
+
+ /**
* Revoke a set of runtime permissions for various apps.
*
* @param requests The permissions to revoke as {@code Map<packageName, List<permission>>}
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 0c190719af57..b9d27e923615 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -25,6 +25,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.IActivityManager;
@@ -637,24 +638,25 @@ public final class PermissionManager {
private static final class PackageNamePermissionQuery {
final String permName;
final String pkgName;
- final int uid;
+ final int userId;
- PackageNamePermissionQuery(@Nullable String permName, @Nullable String pkgName, int uid) {
+ PackageNamePermissionQuery(@Nullable String permName, @Nullable String pkgName,
+ @UserIdInt int userId) {
this.permName = permName;
this.pkgName = pkgName;
- this.uid = uid;
+ this.userId = userId;
}
@Override
public String toString() {
return String.format(
- "PackageNamePermissionQuery(pkgName=\"%s\", permName=\"%s, uid=%s\")",
- pkgName, permName, uid);
+ "PackageNamePermissionQuery(pkgName=\"%s\", permName=\"%s, userId=%s\")",
+ pkgName, permName, userId);
}
@Override
public int hashCode() {
- return Objects.hash(permName, pkgName, uid);
+ return Objects.hash(permName, pkgName, userId);
}
@Override
@@ -670,16 +672,16 @@ public final class PermissionManager {
}
return Objects.equals(permName, other.permName)
&& Objects.equals(pkgName, other.pkgName)
- && uid == other.uid;
+ && userId == other.userId;
}
}
/* @hide */
private static int checkPackageNamePermissionUncached(
- String permName, String pkgName, int uid) {
+ String permName, String pkgName, @UserIdInt int userId) {
try {
return ActivityThread.getPermissionManager().checkPermission(
- permName, pkgName, uid);
+ permName, pkgName, userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -693,7 +695,7 @@ public final class PermissionManager {
@Override
protected Integer recompute(PackageNamePermissionQuery query) {
return checkPackageNamePermissionUncached(
- query.permName, query.pkgName, query.uid);
+ query.permName, query.pkgName, query.userId);
}
};
@@ -702,9 +704,10 @@ public final class PermissionManager {
*
* @hide
*/
- public static int checkPackageNamePermission(String permName, String pkgName, int uid) {
+ public static int checkPackageNamePermission(String permName, String pkgName,
+ @UserIdInt int userId) {
return sPackageNamePermissionCache.query(
- new PackageNamePermissionQuery(permName, pkgName, uid));
+ new PackageNamePermissionQuery(permName, pkgName, userId));
}
/**
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index c1998c6009cf..82f60366a814 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -69,7 +69,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
}
public void onServedEditorChanged(EditorInfo info) {
- if (isDummyOrEmptyEditor(info)) {
+ if (isFallbackOrEmptyEditor(info)) {
mShowOnNextImeRender = false;
}
mFocusedEditor = info;
@@ -167,15 +167,15 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
}
}
- private boolean isDummyOrEmptyEditor(EditorInfo info) {
- // TODO(b/123044812): Handle dummy input gracefully in IME Insets API
+ private boolean isFallbackOrEmptyEditor(EditorInfo info) {
+ // TODO(b/123044812): Handle fallback input gracefully in IME Insets API
return info == null || (info.fieldId <= 0 && info.inputType <= 0);
}
private boolean isServedEditorRendered() {
if (mFocusedEditor == null || mPreRenderedEditor == null
- || isDummyOrEmptyEditor(mFocusedEditor)
- || isDummyOrEmptyEditor(mPreRenderedEditor)) {
+ || isFallbackOrEmptyEditor(mFocusedEditor)
+ || isFallbackOrEmptyEditor(mPreRenderedEditor)) {
// No view is focused or ready.
return false;
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 2ce993dfedca..6ef086b55c41 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -22,8 +22,6 @@ import static android.graphics.Matrix.MSKEW_X;
import static android.graphics.Matrix.MSKEW_Y;
import static android.graphics.Matrix.MTRANS_X;
import static android.graphics.Matrix.MTRANS_Y;
-import static android.view.Surface.ROTATION_270;
-import static android.view.Surface.ROTATION_90;
import static android.view.SurfaceControlProto.HASH_CODE;
import static android.view.SurfaceControlProto.NAME;
@@ -590,6 +588,26 @@ public final class SurfaceControl implements Parcelable {
public boolean containsSecureLayers() {
return mContainsSecureLayers;
}
+
+ /**
+ * Copy content of ScreenshotHardwareBuffer into a hardware bitmap and return it.
+ * Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap
+ * into
+ * a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)}
+ *
+ * CAVEAT: This can be extremely slow; avoid use unless absolutely necessary; prefer to
+ * directly
+ * use the {@link HardwareBuffer} directly.
+ *
+ * @return Bitmap generated from the {@link HardwareBuffer}
+ */
+ public Bitmap asBitmap() {
+ if (mHardwareBuffer == null) {
+ Log.w(TAG, "Failed to take screenshot. Null screenshot object");
+ return null;
+ }
+ return Bitmap.wrapHardwareBuffer(mHardwareBuffer, mColorSpace);
+ }
}
/**
@@ -597,7 +615,7 @@ public final class SurfaceControl implements Parcelable {
* are shared between {@link DisplayCaptureArgs} and {@link LayerCaptureArgs}
* @hide
*/
- public abstract static class CaptureArgs {
+ private abstract static class CaptureArgs {
private final int mPixelFormat;
private final Rect mSourceCrop = new Rect();
private final float mFrameScale;
@@ -615,7 +633,7 @@ public final class SurfaceControl implements Parcelable {
*
* @param <T> A builder that extends {@link Builder}
*/
- public abstract static class Builder<T extends Builder<T>> {
+ abstract static class Builder<T extends Builder<T>> {
private int mPixelFormat = PixelFormat.RGBA_8888;
private final Rect mSourceCrop = new Rect();
private float mFrameScale = 1;
@@ -675,7 +693,6 @@ public final class SurfaceControl implements Parcelable {
private final int mWidth;
private final int mHeight;
private final boolean mUseIdentityTransform;
- private final int mRotation;
private DisplayCaptureArgs(Builder builder) {
super(builder);
@@ -683,7 +700,6 @@ public final class SurfaceControl implements Parcelable {
mWidth = builder.mWidth;
mHeight = builder.mHeight;
mUseIdentityTransform = builder.mUseIdentityTransform;
- mRotation = builder.mRotation;
}
/**
@@ -694,7 +710,6 @@ public final class SurfaceControl implements Parcelable {
private int mWidth;
private int mHeight;
private boolean mUseIdentityTransform;
- private @Surface.Rotation int mRotation = Surface.ROTATION_0;
/**
* Construct a new {@link LayerCaptureArgs} with the set parameters. The builder
@@ -736,26 +751,16 @@ public final class SurfaceControl implements Parcelable {
}
/**
- * Replace whatever transformation (rotation, scaling, translation) the surface
- * layers are currently using with the identity transformation while taking the
- * screenshot.
+ * Replace the rotation transform of the display with the identity transformation while
+ * taking the screenshot. This ensures the screenshot is taken in the ROTATION_0
+ * orientation. Set this value to false if the screenshot should be taken in the
+ * current screen orientation.
*/
public Builder setUseIdentityTransform(boolean useIdentityTransform) {
mUseIdentityTransform = useIdentityTransform;
return this;
}
- /**
- * Apply a custom clockwise rotation to the screenshot, i.e.
- * Surface.ROTATION_0,90,180,270. SurfaceFlinger will always take screenshots in its
- * native portrait orientation by default, so this is useful for returning screenshots
- * that are independent of device orientation.
- */
- public Builder setRotation(@Surface.Rotation int rotation) {
- mRotation = rotation;
- return this;
- }
-
@Override
Builder getThis() {
return this;
@@ -2221,130 +2226,16 @@ public final class SurfaceControl implements Parcelable {
}
/**
- * @see SurfaceControl#screenshot(Rect, int, int, boolean, int)}
- * @hide
- */
- @UnsupportedAppUsage
- public static Bitmap screenshot(Rect sourceCrop, int width, int height, int rotation) {
- return screenshot(sourceCrop, width, height, false, rotation);
- }
-
- /**
- * Copy the current screen contents into a hardware bitmap and return it.
- * Note: If you want to modify the Bitmap in software, you will need to copy the Bitmap into
- * a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)}
+ * Captures all the surfaces in a display and returns a {@link ScreenshotHardwareBuffer} with
+ * the content.
*
- * CAVEAT: Versions of screenshot that return a {@link Bitmap} can be extremely slow; avoid use
- * unless absolutely necessary; prefer the versions that use a {@link HardwareBuffer} such as
- * {@link SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)}.
- *
- * @see SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)}
* @hide
*/
- @UnsupportedAppUsage
- public static Bitmap screenshot(Rect sourceCrop, int width, int height,
- boolean useIdentityTransform, int rotation) {
- // TODO: should take the display as a parameter
- final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
- if (displayToken == null) {
- Log.w(TAG, "Failed to take screenshot because internal display is disconnected");
- return null;
- }
-
- if (rotation == ROTATION_90 || rotation == ROTATION_270) {
- rotation = (rotation == ROTATION_90) ? ROTATION_270 : ROTATION_90;
- }
-
- SurfaceControl.rotateCropForSF(sourceCrop, rotation);
- final ScreenshotHardwareBuffer buffer = screenshotToBuffer(displayToken, sourceCrop, width,
- height, useIdentityTransform, rotation);
-
- if (buffer == null) {
- Log.w(TAG, "Failed to take screenshot");
- return null;
- }
- return Bitmap.wrapHardwareBuffer(buffer.getHardwareBuffer(), buffer.getColorSpace());
- }
-
- /**
- * Captures all the surfaces in a display and returns a {@link HardwareBuffer} with the content.
- *
- * @param display The display to take the screenshot of.
- * @param sourceCrop The portion of the screen to capture into the Bitmap; caller may
- * pass in 'new Rect()' if no cropping is desired.
- * @param width The desired width of the returned bitmap; the raw screen will be
- * scaled down to this size; caller may pass in 0 if no scaling is
- * desired.
- * @param height The desired height of the returned bitmap; the raw screen will
- * be scaled down to this size; caller may pass in 0 if no scaling
- * is desired.
- * @param useIdentityTransform Replace whatever transformation (rotation, scaling, translation)
- * the surface layers are currently using with the identity
- * transformation while taking the screenshot.
- * @param rotation Apply a custom clockwise rotation to the screenshot, i.e.
- * Surface.ROTATION_0,90,180,270. SurfaceFlinger will always take
- * screenshots in its native portrait orientation by default, so
- * this is useful for returning screenshots that are independent of
- * device orientation.
- * @return Returns a HardwareBuffer that contains the captured content.
- * @hide
- */
- public static ScreenshotHardwareBuffer screenshotToBuffer(IBinder display, Rect sourceCrop,
- int width, int height, boolean useIdentityTransform, int rotation) {
- if (display == null) {
- throw new IllegalArgumentException("displayToken must not be null");
- }
-
- DisplayCaptureArgs captureArgs = new DisplayCaptureArgs.Builder(display)
- .setSourceCrop(sourceCrop)
- .setSize(width, height)
- .setUseIdentityTransform(useIdentityTransform)
- .setRotation(rotation)
- .build();
-
+ public static ScreenshotHardwareBuffer captureDisplay(DisplayCaptureArgs captureArgs) {
return nativeCaptureDisplay(captureArgs);
}
/**
- * Like screenshotToBuffer, but if the caller is AID_SYSTEM, allows
- * for the capture of secure layers. This is used for the screen rotation
- * animation where the system server takes screenshots but does
- * not persist them or allow them to leave the server. However in other
- * cases in the system server, we mostly want to omit secure layers
- * like when we take a screenshot on behalf of the assistant.
- *
- * @hide
- */
- public static ScreenshotHardwareBuffer screenshotToBufferWithSecureLayersUnsafe(IBinder display,
- Rect sourceCrop, int width, int height, boolean useIdentityTransform,
- int rotation) {
- if (display == null) {
- throw new IllegalArgumentException("displayToken must not be null");
- }
-
- DisplayCaptureArgs captureArgs = new DisplayCaptureArgs.Builder(display)
- .setSourceCrop(sourceCrop)
- .setSize(width, height)
- .setUseIdentityTransform(useIdentityTransform)
- .setRotation(rotation)
- .setCaptureSecureLayers(true)
- .build();
-
- return nativeCaptureDisplay(captureArgs);
- }
-
- private static void rotateCropForSF(Rect crop, int rot) {
- if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
- int tmp = crop.top;
- crop.top = crop.left;
- crop.left = tmp;
- tmp = crop.right;
- crop.right = crop.bottom;
- crop.bottom = tmp;
- }
- }
-
- /**
* Captures a layer and its children and returns a {@link HardwareBuffer} with the content.
*
* @param layer The root layer to capture.
diff --git a/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl b/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl
index e814ec649087..eb67191e5f54 100644
--- a/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl
+++ b/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl
@@ -29,7 +29,7 @@ import android.view.accessibility.IWindowMagnificationConnectionCallback;
oneway interface IWindowMagnificationConnection {
/**
- * Enables window magnification on specifed display with specified center and scale.
+ * Enables window magnification on specified display with given center and scale and animation.
*
* @param displayId The logical display id.
* @param scale magnification scale.
@@ -41,7 +41,7 @@ oneway interface IWindowMagnificationConnection {
void enableWindowMagnification(int displayId, float scale, float centerX, float centerY);
/**
- * Sets the scale of the window magnifier on specifed display.
+ * Sets the scale of the window magnifier on specified display.
*
* @param displayId The logical display id.
* @param scale magnification scale.
@@ -49,14 +49,14 @@ oneway interface IWindowMagnificationConnection {
void setScale(int displayId, float scale);
/**
- * Disables window magnification on specifed display.
+ * Disables window magnification on specified display with animation.
*
* @param displayId The logical display id.
*/
void disableWindowMagnification(int displayId);
/**
- * Moves the window magnifier on the specifed display.
+ * Moves the window magnifier on the specified display. It has no effect while animating.
*
* @param offsetX the amount in pixels to offset the window magnifier in the X direction, in
* current screen pixels.
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index d5d631ac1dc7..eef27262c699 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -54,7 +54,7 @@ public class BaseInputConnection implements InputConnection {
/** @hide */
protected final InputMethodManager mIMM;
final View mTargetView;
- final boolean mDummyMode;
+ final boolean mFallbackMode;
private Object[] mDefaultComposingSpans;
@@ -64,14 +64,14 @@ public class BaseInputConnection implements InputConnection {
BaseInputConnection(InputMethodManager mgr, boolean fullEditor) {
mIMM = mgr;
mTargetView = null;
- mDummyMode = !fullEditor;
+ mFallbackMode = !fullEditor;
}
public BaseInputConnection(View targetView, boolean fullEditor) {
mIMM = (InputMethodManager)targetView.getContext().getSystemService(
Context.INPUT_METHOD_SERVICE);
mTargetView = targetView;
- mDummyMode = !fullEditor;
+ mFallbackMode = !fullEditor;
}
public static final void removeComposingSpans(Spannable text) {
@@ -189,7 +189,7 @@ public class BaseInputConnection implements InputConnection {
/**
* Default implementation replaces any existing composing text with
- * the given text. In addition, only if dummy mode, a key event is
+ * the given text. In addition, only if fallback mode, a key event is
* sent for the new text and the current editable buffer cleared.
*/
public boolean commitText(CharSequence text, int newCursorPosition) {
@@ -445,7 +445,7 @@ public class BaseInputConnection implements InputConnection {
/**
* The default implementation removes the composing state from the
- * current editable text. In addition, only if dummy mode, a key event is
+ * current editable text. In addition, only if fallback mode, a key event is
* sent for the new text and the current editable buffer cleared.
*/
public boolean finishComposingText() {
@@ -454,7 +454,7 @@ public class BaseInputConnection implements InputConnection {
if (content != null) {
beginBatchEdit();
removeComposingSpans(content);
- // Note: sendCurrentText does nothing unless mDummyMode is set
+ // Note: sendCurrentText does nothing unless mFallbackMode is set
sendCurrentText();
endBatchEdit();
}
@@ -464,10 +464,10 @@ public class BaseInputConnection implements InputConnection {
/**
* The default implementation uses TextUtils.getCapsMode to get the
* cursor caps mode for the current selection position in the editable
- * text, unless in dummy mode in which case 0 is always returned.
+ * text, unless in fallback mode in which case 0 is always returned.
*/
public int getCursorCapsMode(int reqModes) {
- if (mDummyMode) return 0;
+ if (mFallbackMode) return 0;
final Editable content = getEditable();
if (content == null) return 0;
@@ -664,7 +664,7 @@ public class BaseInputConnection implements InputConnection {
content.setSpan(COMPOSING, a, b,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING);
- // Note: sendCurrentText does nothing unless mDummyMode is set
+ // Note: sendCurrentText does nothing unless mFallbackMode is set
sendCurrentText();
endBatchEdit();
}
@@ -715,7 +715,7 @@ public class BaseInputConnection implements InputConnection {
}
private void sendCurrentText() {
- if (!mDummyMode) {
+ if (!mFallbackMode) {
return;
}
diff --git a/core/java/android/view/textclassifier/TextClassificationSession.java b/core/java/android/view/textclassifier/TextClassificationSession.java
index fed3dbf8f49c..00086587819f 100644
--- a/core/java/android/view/textclassifier/TextClassificationSession.java
+++ b/core/java/android/view/textclassifier/TextClassificationSession.java
@@ -20,9 +20,11 @@ import android.annotation.NonNull;
import android.annotation.WorkerThread;
import android.view.textclassifier.SelectionEvent.InvocationMethod;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import java.util.Objects;
+import java.util.function.Supplier;
import sun.misc.Cleaner;
@@ -40,6 +42,9 @@ final class TextClassificationSession implements TextClassifier {
private final TextClassificationContext mClassificationContext;
private final Cleaner mCleaner;
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
private boolean mDestroyed;
TextClassificationSession(TextClassificationContext context, TextClassifier delegate) {
@@ -54,8 +59,7 @@ final class TextClassificationSession implements TextClassifier {
@Override
public TextSelection suggestSelection(TextSelection.Request request) {
- checkDestroyed();
- return mDelegate.suggestSelection(request);
+ return checkDestroyedAndRun(() -> mDelegate.suggestSelection(request));
}
private void initializeRemoteSession() {
@@ -67,77 +71,97 @@ final class TextClassificationSession implements TextClassifier {
@Override
public TextClassification classifyText(TextClassification.Request request) {
- checkDestroyed();
- return mDelegate.classifyText(request);
+ return checkDestroyedAndRun(() -> mDelegate.classifyText(request));
}
@Override
public TextLinks generateLinks(TextLinks.Request request) {
- checkDestroyed();
- return mDelegate.generateLinks(request);
+ return checkDestroyedAndRun(() -> mDelegate.generateLinks(request));
}
@Override
public ConversationActions suggestConversationActions(ConversationActions.Request request) {
- checkDestroyed();
- return mDelegate.suggestConversationActions(request);
+ return checkDestroyedAndRun(() -> mDelegate.suggestConversationActions(request));
}
@Override
public TextLanguage detectLanguage(TextLanguage.Request request) {
- checkDestroyed();
- return mDelegate.detectLanguage(request);
+ return checkDestroyedAndRun(() -> mDelegate.detectLanguage(request));
}
@Override
public int getMaxGenerateLinksTextLength() {
- checkDestroyed();
- return mDelegate.getMaxGenerateLinksTextLength();
+ return checkDestroyedAndRun(mDelegate::getMaxGenerateLinksTextLength);
}
@Override
public void onSelectionEvent(SelectionEvent event) {
- try {
- if (mEventHelper.sanitizeEvent(event)) {
- mDelegate.onSelectionEvent(event);
+ checkDestroyedAndRun(() -> {
+ try {
+ if (mEventHelper.sanitizeEvent(event)) {
+ mDelegate.onSelectionEvent(event);
+ }
+ } catch (Exception e) {
+ // Avoid crashing for event reporting.
+ Log.e(LOG_TAG, "Error reporting text classifier selection event", e);
}
- } catch (Exception e) {
- // Avoid crashing for event reporting.
- Log.e(LOG_TAG, "Error reporting text classifier selection event", e);
- }
+ return null;
+ });
}
@Override
public void onTextClassifierEvent(TextClassifierEvent event) {
- try {
- event.mHiddenTempSessionId = mSessionId;
- mDelegate.onTextClassifierEvent(event);
- } catch (Exception e) {
- // Avoid crashing for event reporting.
- Log.e(LOG_TAG, "Error reporting text classifier event", e);
- }
+ checkDestroyedAndRun(() -> {
+ try {
+ event.mHiddenTempSessionId = mSessionId;
+ mDelegate.onTextClassifierEvent(event);
+ } catch (Exception e) {
+ // Avoid crashing for event reporting.
+ Log.e(LOG_TAG, "Error reporting text classifier event", e);
+ }
+ return null;
+ });
}
@Override
public void destroy() {
- mCleaner.clean();
- mDestroyed = true;
+ synchronized (mLock) {
+ if (!mDestroyed) {
+ mCleaner.clean();
+ mDestroyed = true;
+ }
+ }
}
@Override
public boolean isDestroyed() {
- return mDestroyed;
+ synchronized (mLock) {
+ return mDestroyed;
+ }
}
/**
- * @throws IllegalStateException if this TextClassification session has been destroyed.
+ * Check whether the TextClassification Session was destroyed before and after the actual API
+ * invocation, and return response if not.
+ *
+ * @param responseSupplier a Supplier that represents a TextClassifier call
+ * @return the response of the TextClassifier call
+ * @throws IllegalStateException if this TextClassification session was destroyed before the
+ * call returned
* @see #isDestroyed()
* @see #destroy()
*/
- private void checkDestroyed() {
- if (mDestroyed) {
- throw new IllegalStateException("This TextClassification session has been destroyed");
+ private <T> T checkDestroyedAndRun(Supplier<T> responseSupplier) {
+ if (!isDestroyed()) {
+ T response = responseSupplier.get();
+ synchronized (mLock) {
+ if (!mDestroyed) {
+ return response;
+ }
+ }
}
+ throw new IllegalStateException(
+ "This TextClassification session has been destroyed");
}
/**
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 7683067958d8..60f8bb7ebe6c 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -154,6 +154,10 @@ public class Editor {
// Specifies whether to use the magnifier when pressing the insertion or selection handles.
private static final boolean FLAG_USE_MAGNIFIER = true;
+ // Specifies how far to make the cursor start float when drag the cursor away from the
+ // beginning or end of the line.
+ private static final int CURSOR_START_FLOAT_DISTANCE_PX = 20;
+
private static final int DELAY_BEFORE_HANDLE_FADES_OUT = 4000;
private static final int RECENT_CUT_COPY_DURATION_MS = 15 * 1000; // 15 seconds in millis
@@ -289,6 +293,9 @@ public class Editor {
private boolean mRenderCursorRegardlessTiming;
private Blink mBlink;
+ // Whether to let magnifier draw cursor on its surface. This is for floating cursor effect.
+ // And it can only be true when |mNewMagnifierEnabled| is true.
+ private boolean mDrawCursorOnMagnifier;
boolean mCursorVisible = true;
boolean mSelectAllOnFocus;
boolean mTextIsSelectable;
@@ -890,7 +897,7 @@ public class Editor {
}
boolean enabled = windowSupportsHandles && mTextView.getLayout() != null;
- mInsertionControllerEnabled = enabled && isCursorVisible();
+ mInsertionControllerEnabled = enabled && (mDrawCursorOnMagnifier || isCursorVisible());
mSelectionControllerEnabled = enabled && mTextView.textCanBeSelected();
if (!mInsertionControllerEnabled) {
@@ -5101,26 +5108,38 @@ public class Editor {
final int[] textViewLocationOnScreen = new int[2];
mTextView.getLocationOnScreen(textViewLocationOnScreen);
final float touchXInView = event.getRawX() - textViewLocationOnScreen[0];
- float leftBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
- float rightBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
- if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_END) ^ rtl)) {
- leftBound += getHorizontal(mTextView.getLayout(), otherHandleOffset);
- } else {
- leftBound += mTextView.getLayout().getLineLeft(lineNumber);
- }
- if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_START) ^ rtl)) {
- rightBound += getHorizontal(mTextView.getLayout(), otherHandleOffset);
+ float leftBound, rightBound;
+ if (mNewMagnifierEnabled) {
+ leftBound = 0;
+ rightBound = mTextView.getWidth();
+ if (touchXInView < leftBound || touchXInView > rightBound) {
+ // The touch is too far from the current line / selection, so hide the magnifier.
+ return false;
+ }
} else {
- rightBound += mTextView.getLayout().getLineRight(lineNumber);
- }
- leftBound *= mTextViewScaleX;
- rightBound *= mTextViewScaleX;
- final float contentWidth = Math.round(mMagnifierAnimator.mMagnifier.getWidth()
- / mMagnifierAnimator.mMagnifier.getZoom());
- if (touchXInView < leftBound - contentWidth / 2
- || touchXInView > rightBound + contentWidth / 2) {
- // The touch is too far from the current line / selection, so hide the magnifier.
- return false;
+ leftBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
+ rightBound = mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
+ if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_END)
+ ^ rtl)) {
+ leftBound += getHorizontal(mTextView.getLayout(), otherHandleOffset);
+ } else {
+ leftBound += mTextView.getLayout().getLineLeft(lineNumber);
+ }
+ if (sameLineSelection && ((trigger == MagnifierHandleTrigger.SELECTION_START)
+ ^ rtl)) {
+ rightBound += getHorizontal(mTextView.getLayout(), otherHandleOffset);
+ } else {
+ rightBound += mTextView.getLayout().getLineRight(lineNumber);
+ }
+ leftBound *= mTextViewScaleX;
+ rightBound *= mTextViewScaleX;
+ final float contentWidth = Math.round(mMagnifierAnimator.mMagnifier.getWidth()
+ / mMagnifierAnimator.mMagnifier.getZoom());
+ if (touchXInView < leftBound - contentWidth / 2
+ || touchXInView > rightBound + contentWidth / 2) {
+ // The touch is too far from the current line / selection, so hide the magnifier.
+ return false;
+ }
}
final float scaledTouchXInView;
@@ -5178,7 +5197,8 @@ public class Editor {
final Rect magnifierRect = new Rect(magnifierTopLeft.x, magnifierTopLeft.y,
magnifierTopLeft.x + mMagnifierAnimator.mMagnifier.getWidth(),
magnifierTopLeft.y + mMagnifierAnimator.mMagnifier.getHeight());
- setVisible(!handleOverlapsMagnifier(HandleView.this, magnifierRect));
+ setVisible(!handleOverlapsMagnifier(HandleView.this, magnifierRect)
+ && !mDrawCursorOnMagnifier);
final HandleView otherHandle = getOtherSelectionHandle();
if (otherHandle != null) {
otherHandle.setVisible(!handleOverlapsMagnifier(otherHandle, magnifierRect));
@@ -5208,7 +5228,20 @@ public class Editor {
lineLeft += mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
int lineRight = (int) layout.getLineRight(line);
lineRight += mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
- mMagnifierAnimator.mMagnifier.setSourceHorizontalBounds(lineLeft, lineRight);
+ mDrawCursorOnMagnifier =
+ showPosInView.x < lineLeft - CURSOR_START_FLOAT_DISTANCE_PX
+ || showPosInView.x > lineRight + CURSOR_START_FLOAT_DISTANCE_PX;
+ mMagnifierAnimator.mMagnifier.setDrawCursor(
+ mDrawCursorOnMagnifier, mDrawableForCursor);
+ boolean cursorVisible = mCursorVisible;
+ // Updates cursor visibility, so that the real cursor and the float cursor on
+ // magnifier surface won't appear at the same time.
+ mCursorVisible = !mDrawCursorOnMagnifier;
+ if (mCursorVisible && !cursorVisible) {
+ // When the real cursor is a drawable, hiding/showing it would change its
+ // bounds. So, call updateCursorPosition() to correct its position.
+ updateCursorPosition();
+ }
final int lineHeight =
layout.getLineBottomWithoutSpacing(line) - layout.getLineTop(line);
float zoom = mInitialZoom;
@@ -5230,6 +5263,11 @@ public class Editor {
if (mMagnifierAnimator != null) {
mMagnifierAnimator.dismiss();
mRenderCursorRegardlessTiming = false;
+ mDrawCursorOnMagnifier = false;
+ if (!mCursorVisible) {
+ mCursorVisible = true;
+ mTextView.invalidate();
+ }
resumeBlink();
setVisible(true);
final HandleView otherHandle = getOtherSelectionHandle();
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 89206fda39f3..c72eed45e794 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -149,9 +149,6 @@ public final class Magnifier {
private int mLeftCutWidth = 0;
// The width of the cut region on the right edge of the pixel copy source rect.
private int mRightCutWidth = 0;
- // The horizontal bounds of the content source in pixels, relative to the view.
- private int mLeftBound = Integer.MIN_VALUE;
- private int mRightBound = Integer.MAX_VALUE;
// The width of the ramp region in pixels on the left & right sides of the fish-eye effect.
private final int mRamp;
@@ -244,18 +241,6 @@ public final class Magnifier {
}
/**
- * Sets the horizontal bounds of the source when showing the magnifier.
- * This is used for new style magnifier. e.g. limit the source bounds by the text line bounds.
- *
- * @param left the left of the bounds, relative to the view.
- * @param right the right of the bounds, relative to the view.
- */
- void setSourceHorizontalBounds(int left, int right) {
- mLeftBound = left;
- mRightBound = right;
- }
-
- /**
* Shows the magnifier on the screen. The method takes the coordinates of the center
* of the content source going to be magnified and copied to the magnifier. The coordinates
* are relative to the top left corner of the magnified view. The magnifier will be
@@ -280,6 +265,14 @@ public final class Magnifier {
sourceCenterY + mDefaultVerticalSourceToMagnifierOffset);
}
+ private Drawable mCursorDrawable;
+ private boolean mDrawCursorEnabled;
+
+ void setDrawCursor(boolean enabled, Drawable cursorDrawable) {
+ mDrawCursorEnabled = enabled;
+ mCursorDrawable = cursorDrawable;
+ }
+
/**
* Shows the magnifier on the screen at a position that is independent from its content
* position. The first two arguments represent the coordinates of the center of the
@@ -309,8 +302,7 @@ public final class Magnifier {
magnifierCenterX = mClampedCenterZoomCoords.x - mViewCoordinatesInSurface[0];
magnifierCenterY = mClampedCenterZoomCoords.y - mViewCoordinatesInSurface[1];
- // mLeftBound & mRightBound (typically the text line left/right) is for magnified
- // content. However the PixelCopy requires the pre-magnified bounds.
+ // PixelCopy requires the pre-magnified bounds.
// The below logic calculates the leftBound & rightBound for the pre-magnified bounds.
final float rampPre =
(mSourceWidth - (mSourceWidth - 2 * mRamp) / mZoom) / 2;
@@ -318,7 +310,7 @@ public final class Magnifier {
// Calculates the pre-zoomed left edge.
// The leftEdge moves from the left of view towards to sourceCenterX, considering the
// fisheye-like zooming.
- final float x0 = sourceCenterX - mSourceWidth / 2;
+ final float x0 = sourceCenterX - mSourceWidth / 2f;
final float rampX0 = x0 + mRamp;
float leftEdge = 0;
if (leftEdge > rampX0) {
@@ -330,12 +322,12 @@ public final class Magnifier {
// increase per ramp zoom (ramp / rampPre).
leftEdge = x0 + rampPre - (rampX0 - leftEdge) * rampPre / mRamp;
}
- int leftBound = Math.min(Math.max((int) leftEdge, mLeftBound), mRightBound);
+ int leftBound = Math.min((int) leftEdge, mView.getWidth());
// Calculates the pre-zoomed right edge.
// The rightEdge moves from the right of view towards to sourceCenterX, considering the
// fisheye-like zooming.
- final float x1 = sourceCenterX + mSourceWidth / 2;
+ final float x1 = sourceCenterX + mSourceWidth / 2f;
final float rampX1 = x1 - mRamp;
float rightEdge = mView.getWidth();
if (rightEdge < rampX1) {
@@ -347,7 +339,7 @@ public final class Magnifier {
// increase per ramp zoom (ramp / rampPre).
rightEdge = x1 - rampPre + (rightEdge - rampX1) * rampPre / mRamp;
}
- int rightBound = Math.max(leftBound, Math.min((int) rightEdge, mRightBound));
+ int rightBound = Math.max(leftBound, (int) rightEdge);
// Gets the startX for new style, which should be bounded by the horizontal bounds.
// Also calculates the left/right cut width for pixel copy.
@@ -772,6 +764,23 @@ public final class Magnifier {
}
}
+ private void maybeDrawCursor(Canvas canvas) {
+ if (mDrawCursorEnabled) {
+ if (mCursorDrawable != null) {
+ mCursorDrawable.setBounds(
+ mSourceWidth / 2, 0,
+ mSourceWidth / 2 + mCursorDrawable.getIntrinsicWidth(), mSourceHeight);
+ mCursorDrawable.draw(canvas);
+ } else {
+ Paint paint = new Paint();
+ paint.setColor(Color.BLACK); // The cursor on magnifier is by default in black.
+ canvas.drawRect(
+ new Rect(mSourceWidth / 2 - 1, 0, mSourceWidth / 2 + 1, mSourceHeight),
+ paint);
+ }
+ }
+ }
+
private void performPixelCopy(final int startXInSurface, final int startYInSurface,
final boolean updateWindowPosition) {
if (mContentCopySurface.mSurface == null || !mContentCopySurface.mSurface.isValid()) {
@@ -827,8 +836,10 @@ public final class Magnifier {
final Rect dstRect = new Rect(mLeftCutWidth, 0,
mSourceWidth - mRightCutWidth, bitmap.getHeight());
can.drawBitmap(bitmap, null, dstRect, null);
+ maybeDrawCursor(can);
mWindow.updateContent(newBitmap);
} else {
+ maybeDrawCursor(new Canvas(bitmap));
mWindow.updateContent(bitmap);
}
}
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 201626abd820..f5bef0b006f5 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -74,6 +74,10 @@ public class BinderCallsStats implements BinderInternal.Observer {
// Whether to collect all the data: cpu + exceptions + reply/request sizes.
private boolean mDetailedTracking = DETAILED_TRACKING_DEFAULT;
+ // If set to true, indicates that all transactions for specific UIDs are being
+ // recorded, ignoring sampling. The UidEntry.recordAllTransactions flag is also set
+ // for the UIDs being tracked.
+ private boolean mRecordingAllTransactionsForUid;
// Sampling period to control how often to track CPU usage. 1 means all calls, 100 means ~1 out
// of 100 requests.
private int mPeriodicSamplingInterval = PERIODIC_SAMPLING_INTERVAL_DEFAULT;
@@ -178,7 +182,8 @@ public class BinderCallsStats implements BinderInternal.Observer {
@Override
@Nullable
public CallSession callStarted(Binder binder, int code, int workSourceUid) {
- if (mDeviceState == null || mDeviceState.isCharging()) {
+ if (!mRecordingAllTransactionsForUid
+ && (mDeviceState == null || mDeviceState.isCharging())) {
return null;
}
@@ -190,7 +195,9 @@ public class BinderCallsStats implements BinderInternal.Observer {
s.exceptionThrown = false;
s.cpuTimeStarted = -1;
s.timeStarted = -1;
- if (shouldRecordDetailedData()) {
+ s.recordedCall = shouldRecordDetailedData();
+
+ if (mRecordingAllTransactionsForUid || s.recordedCall) {
s.cpuTimeStarted = getThreadTimeMicro();
s.timeStarted = getElapsedRealtimeMicro();
}
@@ -218,8 +225,17 @@ public class BinderCallsStats implements BinderInternal.Observer {
private void processCallEnded(CallSession s,
int parcelRequestSize, int parcelReplySize, int workSourceUid) {
- // Non-negative time signals we need to record data for this call.
- final boolean recordCall = s.cpuTimeStarted >= 0;
+ UidEntry uidEntry = null;
+ final boolean recordCall;
+ if (s.recordedCall) {
+ recordCall = true;
+ } else if (mRecordingAllTransactionsForUid) {
+ uidEntry = getUidEntry(workSourceUid);
+ recordCall = uidEntry.recordAllTransactions;
+ } else {
+ recordCall = false;
+ }
+
final long duration;
final long latencyDuration;
if (recordCall) {
@@ -238,14 +254,17 @@ public class BinderCallsStats implements BinderInternal.Observer {
synchronized (mLock) {
// This was already checked in #callStart but check again while synchronized.
- if (mDeviceState == null || mDeviceState.isCharging()) {
+ if (!mRecordingAllTransactionsForUid
+ && (mDeviceState == null || mDeviceState.isCharging())) {
return;
}
- final UidEntry uidEntry = getUidEntry(workSourceUid);
+ if (uidEntry == null) {
+ uidEntry = getUidEntry(workSourceUid);
+ }
+
uidEntry.callCount++;
uidEntry.incrementalCallCount++;
-
if (recordCall) {
uidEntry.cpuTimeMicros += duration;
uidEntry.recordedCallCount++;
@@ -357,28 +376,67 @@ public class BinderCallsStats implements BinderInternal.Observer {
for (int entryIdx = 0; entryIdx < uidEntriesSize; entryIdx++) {
final UidEntry entry = mUidEntries.valueAt(entryIdx);
for (CallStat stat : entry.getCallStatsList()) {
- ExportedCallStat exported = new ExportedCallStat();
- exported.workSourceUid = entry.workSourceUid;
- exported.callingUid = stat.callingUid;
- exported.className = stat.binderClass.getName();
- exported.binderClass = stat.binderClass;
- exported.transactionCode = stat.transactionCode;
- exported.screenInteractive = stat.screenInteractive;
- exported.cpuTimeMicros = stat.cpuTimeMicros;
- exported.maxCpuTimeMicros = stat.maxCpuTimeMicros;
- exported.latencyMicros = stat.latencyMicros;
- exported.maxLatencyMicros = stat.maxLatencyMicros;
- exported.recordedCallCount = stat.recordedCallCount;
- exported.callCount = stat.callCount;
- exported.maxRequestSizeBytes = stat.maxRequestSizeBytes;
- exported.maxReplySizeBytes = stat.maxReplySizeBytes;
- exported.exceptionCount = stat.exceptionCount;
- resultCallStats.add(exported);
+ resultCallStats.add(getExportedCallStat(entry.workSourceUid, stat));
}
}
}
// Resolve codes outside of the lock since it can be slow.
+ resolveBinderMethodNames(resultCallStats);
+
+ // Debug entries added to help validate the data.
+ if (mAddDebugEntries && mBatteryStopwatch != null) {
+ resultCallStats.add(createDebugEntry("start_time_millis", mStartElapsedTime));
+ resultCallStats.add(createDebugEntry("end_time_millis", SystemClock.elapsedRealtime()));
+ resultCallStats.add(
+ createDebugEntry("battery_time_millis", mBatteryStopwatch.getMillis()));
+ resultCallStats.add(createDebugEntry("sampling_interval", mPeriodicSamplingInterval));
+ }
+
+ return resultCallStats;
+ }
+
+ /**
+ * This method is expensive to call.
+ */
+ public ArrayList<ExportedCallStat> getExportedCallStats(int workSourceUid) {
+ ArrayList<ExportedCallStat> resultCallStats = new ArrayList<>();
+ synchronized (mLock) {
+ final UidEntry entry = getUidEntry(workSourceUid);
+ for (CallStat stat : entry.getCallStatsList()) {
+ resultCallStats.add(getExportedCallStat(workSourceUid, stat));
+ }
+ }
+
+ // Resolve codes outside of the lock since it can be slow.
+ resolveBinderMethodNames(resultCallStats);
+
+ return resultCallStats;
+ }
+
+ private ExportedCallStat getExportedCallStat(int workSourceUid, CallStat stat) {
+ ExportedCallStat exported = new ExportedCallStat();
+ exported.workSourceUid = workSourceUid;
+ exported.callingUid = stat.callingUid;
+ exported.className = stat.binderClass.getName();
+ exported.binderClass = stat.binderClass;
+ exported.transactionCode = stat.transactionCode;
+ exported.screenInteractive = stat.screenInteractive;
+ exported.cpuTimeMicros = stat.cpuTimeMicros;
+ exported.maxCpuTimeMicros = stat.maxCpuTimeMicros;
+ exported.latencyMicros = stat.latencyMicros;
+ exported.maxLatencyMicros = stat.maxLatencyMicros;
+ exported.recordedCallCount = stat.recordedCallCount;
+ exported.callCount = stat.callCount;
+ exported.maxRequestSizeBytes = stat.maxRequestSizeBytes;
+ exported.maxReplySizeBytes = stat.maxReplySizeBytes;
+ exported.exceptionCount = stat.exceptionCount;
+ return exported;
+ }
+
+ private void resolveBinderMethodNames(
+ ArrayList<ExportedCallStat> resultCallStats) {
+ // Resolve codes outside of the lock since it can be slow.
ExportedCallStat previous = null;
String previousMethodName = null;
resultCallStats.sort(BinderCallsStats::compareByBinderClassAndCode);
@@ -398,17 +456,6 @@ public class BinderCallsStats implements BinderInternal.Observer {
exported.methodName = methodName;
previous = exported;
}
-
- // Debug entries added to help validate the data.
- if (mAddDebugEntries && mBatteryStopwatch != null) {
- resultCallStats.add(createDebugEntry("start_time_millis", mStartElapsedTime));
- resultCallStats.add(createDebugEntry("end_time_millis", SystemClock.elapsedRealtime()));
- resultCallStats.add(
- createDebugEntry("battery_time_millis", mBatteryStopwatch.getMillis()));
- resultCallStats.add(createDebugEntry("sampling_interval", mPeriodicSamplingInterval));
- }
-
- return resultCallStats;
}
private ExportedCallStat createDebugEntry(String variableName, long value) {
@@ -432,33 +479,24 @@ public class BinderCallsStats implements BinderInternal.Observer {
}
/** Writes the collected statistics to the supplied {@link PrintWriter}.*/
- public void dump(PrintWriter pw, AppIdToPackageMap packageMap, boolean verbose) {
+ public void dump(PrintWriter pw, AppIdToPackageMap packageMap, int workSourceUid,
+ boolean verbose) {
synchronized (mLock) {
- dumpLocked(pw, packageMap, verbose);
+ dumpLocked(pw, packageMap, workSourceUid, verbose);
}
}
- private void dumpLocked(PrintWriter pw, AppIdToPackageMap packageMap, boolean verbose) {
- long totalCallsCount = 0;
- long totalRecordedCallsCount = 0;
- long totalCpuTime = 0;
+ private void dumpLocked(PrintWriter pw, AppIdToPackageMap packageMap, int workSourceUid,
+ boolean verbose) {
+ if (workSourceUid != Process.INVALID_UID) {
+ verbose = true;
+ }
pw.print("Start time: ");
pw.println(DateFormat.format("yyyy-MM-dd HH:mm:ss", mStartCurrentTime));
pw.print("On battery time (ms): ");
pw.println(mBatteryStopwatch != null ? mBatteryStopwatch.getMillis() : 0);
pw.println("Sampling interval period: " + mPeriodicSamplingInterval);
- final List<UidEntry> entries = new ArrayList<>();
- final int uidEntriesSize = mUidEntries.size();
- for (int i = 0; i < uidEntriesSize; i++) {
- UidEntry e = mUidEntries.valueAt(i);
- entries.add(e);
- totalCpuTime += e.cpuTimeMicros;
- totalRecordedCallsCount += e.recordedCallCount;
- totalCallsCount += e.callCount;
- }
-
- entries.sort(Comparator.<UidEntry>comparingDouble(value -> value.cpuTimeMicros).reversed());
final String datasetSizeDesc = verbose ? "" : "(top 90% by cpu time) ";
final StringBuilder sb = new StringBuilder();
pw.println("Per-UID raw data " + datasetSizeDesc
@@ -467,10 +505,15 @@ public class BinderCallsStats implements BinderInternal.Observer {
+ "latency_time_micros, max_latency_time_micros, exception_count, "
+ "max_request_size_bytes, max_reply_size_bytes, recorded_call_count, "
+ "call_count):");
- final List<ExportedCallStat> exportedCallStats = getExportedCallStats();
+ final List<ExportedCallStat> exportedCallStats;
+ if (workSourceUid != Process.INVALID_UID) {
+ exportedCallStats = getExportedCallStats(workSourceUid);
+ } else {
+ exportedCallStats = getExportedCallStats();
+ }
exportedCallStats.sort(BinderCallsStats::compareByCpuDesc);
for (ExportedCallStat e : exportedCallStats) {
- if (e.methodName.startsWith(DEBUG_ENTRY_PREFIX)) {
+ if (e.methodName != null && e.methodName.startsWith(DEBUG_ENTRY_PREFIX)) {
// Do not dump debug entries.
continue;
}
@@ -494,6 +537,30 @@ public class BinderCallsStats implements BinderInternal.Observer {
pw.println(sb);
}
pw.println();
+ final List<UidEntry> entries = new ArrayList<>();
+ long totalCallsCount = 0;
+ long totalRecordedCallsCount = 0;
+ long totalCpuTime = 0;
+
+ if (workSourceUid != Process.INVALID_UID) {
+ UidEntry e = getUidEntry(workSourceUid);
+ entries.add(e);
+ totalCpuTime += e.cpuTimeMicros;
+ totalRecordedCallsCount += e.recordedCallCount;
+ totalCallsCount += e.callCount;
+ } else {
+ final int uidEntriesSize = mUidEntries.size();
+ for (int i = 0; i < uidEntriesSize; i++) {
+ UidEntry e = mUidEntries.valueAt(i);
+ entries.add(e);
+ totalCpuTime += e.cpuTimeMicros;
+ totalRecordedCallsCount += e.recordedCallCount;
+ totalCallsCount += e.callCount;
+ }
+ entries.sort(
+ Comparator.<UidEntry>comparingDouble(value -> value.cpuTimeMicros).reversed());
+ }
+
pw.println("Per-UID Summary " + datasetSizeDesc
+ "(cpu_time, % of total cpu_time, recorded_call_count, call_count, package/uid):");
final List<UidEntry> summaryEntries = verbose ? entries
@@ -505,10 +572,13 @@ public class BinderCallsStats implements BinderInternal.Observer {
entry.recordedCallCount, entry.callCount, uidStr));
}
pw.println();
- pw.println(String.format(" Summary: total_cpu_time=%d, "
- + "calls_count=%d, avg_call_cpu_time=%.0f",
- totalCpuTime, totalCallsCount, (double) totalCpuTime / totalRecordedCallsCount));
- pw.println();
+ if (workSourceUid == Process.INVALID_UID) {
+ pw.println(String.format(" Summary: total_cpu_time=%d, "
+ + "calls_count=%d, avg_call_cpu_time=%.0f",
+ totalCpuTime, totalCallsCount,
+ (double) totalCpuTime / totalRecordedCallsCount));
+ pw.println();
+ }
pw.println("Exceptions thrown (exception_count, class_name):");
final List<Pair<String, Integer>> exceptionEntries = new ArrayList<>();
@@ -590,6 +660,22 @@ public class BinderCallsStats implements BinderInternal.Observer {
}
}
+ /**
+ * Marks the specified work source UID for total binder call tracking: detailed information
+ * will be recorded for all calls from this source ID.
+ *
+ * This is expensive and can cause memory pressure, therefore this mode should only be used
+ * for debugging.
+ */
+ public void recordAllCallsForWorkSourceUid(int workSourceUid) {
+ setDetailedTracking(true);
+
+ Slog.i(TAG, "Recording all Binder calls for UID: " + workSourceUid);
+ UidEntry uidEntry = getUidEntry(workSourceUid);
+ uidEntry.recordAllTransactions = true;
+ mRecordingAllTransactionsForUid = true;
+ }
+
public void setAddDebugEntries(boolean addDebugEntries) {
mAddDebugEntries = addDebugEntries;
}
@@ -637,6 +723,7 @@ public class BinderCallsStats implements BinderInternal.Observer {
if (mBatteryStopwatch != null) {
mBatteryStopwatch.reset();
}
+ mRecordingAllTransactionsForUid = false;
}
}
@@ -767,6 +854,8 @@ public class BinderCallsStats implements BinderInternal.Observer {
public long cpuTimeMicros;
// Call count that gets reset after delivery to BatteryStats
public long incrementalCallCount;
+ // Indicates that all transactions for the UID must be tracked
+ public boolean recordAllTransactions;
UidEntry(int uid) {
this.workSourceUid = uid;
diff --git a/core/java/com/android/internal/os/BinderInternal.java b/core/java/com/android/internal/os/BinderInternal.java
index f14d5f2bbbeb..2645b8e84cf1 100644
--- a/core/java/com/android/internal/os/BinderInternal.java
+++ b/core/java/com/android/internal/os/BinderInternal.java
@@ -85,9 +85,10 @@ public class BinderInternal {
long timeStarted;
// Should be set to one when an exception is thrown.
boolean exceptionThrown;
+ // Detailed information should be recorded for this call when it ends.
+ public boolean recordedCall;
}
-
/**
* Responsible for resolving a work source.
*/
diff --git a/services/core/java/com/android/server/wm/ProtoLogGroup.java b/core/java/com/android/internal/protolog/ProtoLogGroup.java
index 51725cecbc74..73d148c1f233 100644
--- a/services/core/java/com/android/server/wm/ProtoLogGroup.java
+++ b/core/java/com/android/internal/protolog/ProtoLogGroup.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,11 +14,9 @@
* limitations under the License.
*/
-package com.android.server.wm;
+package com.android.internal.protolog;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.protolog.common.IProtoLogGroup;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.IProtoLogGroup;
/**
* Defines logging groups for ProtoLog.
@@ -118,16 +116,6 @@ public enum ProtoLogGroup implements IProtoLogGroup {
this.mLogToLogcat = logToLogcat;
}
- /**
- * Test function for automated integration tests. Can be also called manually from adb shell.
- */
- @VisibleForTesting
- public static void testProtoLog() {
- ProtoLog.e(ProtoLogGroup.TEST_GROUP,
- "Test completed successfully: %b %d %o %x %e %g %f %% %s.",
- true, 1, 2, 3, 0.4, 0.5, 0.6, "ok");
- }
-
private static class Consts {
private static final String TAG_WM = "WindowManager";
diff --git a/services/core/java/com/android/server/protolog/ProtoLogImpl.java b/core/java/com/android/internal/protolog/ProtoLogImpl.java
index c9d42c854b54..6874f10e6abc 100644
--- a/services/core/java/com/android/server/protolog/ProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/ProtoLogImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,20 +14,20 @@
* limitations under the License.
*/
-package com.android.server.protolog;
-
-import static com.android.server.protolog.ProtoLogFileProto.LOG;
-import static com.android.server.protolog.ProtoLogFileProto.MAGIC_NUMBER;
-import static com.android.server.protolog.ProtoLogFileProto.MAGIC_NUMBER_H;
-import static com.android.server.protolog.ProtoLogFileProto.MAGIC_NUMBER_L;
-import static com.android.server.protolog.ProtoLogFileProto.REAL_TIME_TO_ELAPSED_TIME_OFFSET_MILLIS;
-import static com.android.server.protolog.ProtoLogFileProto.VERSION;
-import static com.android.server.protolog.ProtoLogMessage.BOOLEAN_PARAMS;
-import static com.android.server.protolog.ProtoLogMessage.DOUBLE_PARAMS;
-import static com.android.server.protolog.ProtoLogMessage.ELAPSED_REALTIME_NANOS;
-import static com.android.server.protolog.ProtoLogMessage.MESSAGE_HASH;
-import static com.android.server.protolog.ProtoLogMessage.SINT64_PARAMS;
-import static com.android.server.protolog.ProtoLogMessage.STR_PARAMS;
+package com.android.internal.protolog;
+
+import static com.android.internal.protolog.ProtoLogFileProto.LOG;
+import static com.android.internal.protolog.ProtoLogFileProto.MAGIC_NUMBER;
+import static com.android.internal.protolog.ProtoLogFileProto.MAGIC_NUMBER_H;
+import static com.android.internal.protolog.ProtoLogFileProto.MAGIC_NUMBER_L;
+import static com.android.internal.protolog.ProtoLogFileProto.REAL_TIME_TO_ELAPSED_TIME_OFFSET_MILLIS;
+import static com.android.internal.protolog.ProtoLogFileProto.VERSION;
+import static com.android.internal.protolog.ProtoLogMessage.BOOLEAN_PARAMS;
+import static com.android.internal.protolog.ProtoLogMessage.DOUBLE_PARAMS;
+import static com.android.internal.protolog.ProtoLogMessage.ELAPSED_REALTIME_NANOS;
+import static com.android.internal.protolog.ProtoLogMessage.MESSAGE_HASH;
+import static com.android.internal.protolog.ProtoLogMessage.SINT64_PARAMS;
+import static com.android.internal.protolog.ProtoLogMessage.STR_PARAMS;
import android.annotation.Nullable;
import android.os.ShellCommand;
@@ -36,10 +36,9 @@ import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.protolog.common.IProtoLogGroup;
-import com.android.server.protolog.common.LogDataType;
+import com.android.internal.protolog.common.IProtoLogGroup;
+import com.android.internal.protolog.common.LogDataType;
import com.android.internal.util.TraceBuffer;
-import com.android.server.wm.ProtoLogGroup;
import java.io.File;
import java.io.IOException;
@@ -62,7 +61,7 @@ public class ProtoLogImpl {
* Must be invoked after every action that could change the result of {@link #isEnabled}, eg.
* starting / stopping proto log, or enabling / disabling log groups.
*/
- static Runnable sCacheUpdater = () -> { };
+ public static Runnable sCacheUpdater = () -> { };
private static void addLogGroupEnum(IProtoLogGroup[] config) {
for (IProtoLogGroup group : config) {
@@ -289,9 +288,7 @@ public class ProtoLogImpl {
}
}
-
- @VisibleForTesting
- ProtoLogImpl(File file, int bufferCapacity, ProtoLogViewerConfigReader viewerConfig) {
+ public ProtoLogImpl(File file, int bufferCapacity, ProtoLogViewerConfigReader viewerConfig) {
mLogFile = file;
mBuffer = new TraceBuffer(bufferCapacity);
mViewerConfig = viewerConfig;
diff --git a/services/core/java/com/android/server/protolog/ProtoLogViewerConfigReader.java b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
index 494421717800..e381d30da524 100644
--- a/services/core/java/com/android/server/protolog/ProtoLogViewerConfigReader.java
+++ b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-package com.android.server.protolog;
-
-import static com.android.server.protolog.ProtoLogImpl.logAndPrintln;
+package com.android.internal.protolog;
import org.json.JSONException;
import org.json.JSONObject;
@@ -80,16 +78,17 @@ public class ProtoLogViewerConfigReader {
// Not a messageHash - skip it
}
}
- logAndPrintln(pw, "Loaded " + mLogMessageMap.size() + " log definitions from "
- + viewerConfigFilename);
+ ProtoLogImpl.logAndPrintln(pw, "Loaded " + mLogMessageMap.size()
+ + " log definitions from " + viewerConfigFilename);
} catch (FileNotFoundException e) {
- logAndPrintln(pw, "Unable to load log definitions: File "
+ ProtoLogImpl.logAndPrintln(pw, "Unable to load log definitions: File "
+ viewerConfigFilename + " not found." + e);
} catch (IOException e) {
- logAndPrintln(pw, "Unable to load log definitions: IOException while reading "
+ ProtoLogImpl.logAndPrintln(pw,
+ "Unable to load log definitions: IOException while reading "
+ viewerConfigFilename + ". " + e);
} catch (JSONException e) {
- logAndPrintln(pw,
+ ProtoLogImpl.logAndPrintln(pw,
"Unable to load log definitions: JSON parsing exception while reading "
+ viewerConfigFilename + ". " + e);
}
diff --git a/services/core/java/com/android/server/protolog/common/BitmaskConversionException.java b/core/java/com/android/internal/protolog/common/BitmaskConversionException.java
index 7bb27b2d9bcd..68b9d6910b57 100644
--- a/services/core/java/com/android/server/protolog/common/BitmaskConversionException.java
+++ b/core/java/com/android/internal/protolog/common/BitmaskConversionException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.protolog.common;
+package com.android.internal.protolog.common;
/**
* Error while converting a bitmask representing a list of LogDataTypes.
diff --git a/services/core/java/com/android/server/protolog/common/IProtoLogGroup.java b/core/java/com/android/internal/protolog/common/IProtoLogGroup.java
index 2c65341453e9..e3db46832a6f 100644
--- a/services/core/java/com/android/server/protolog/common/IProtoLogGroup.java
+++ b/core/java/com/android/internal/protolog/common/IProtoLogGroup.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.protolog.common;
+package com.android.internal.protolog.common;
/**
* Defines a log group configuration object for ProtoLog. Should be implemented as en enum.
diff --git a/services/core/java/com/android/server/protolog/common/InvalidFormatStringException.java b/core/java/com/android/internal/protolog/common/InvalidFormatStringException.java
index 947bf98eea3c..97d3dfb7e6c2 100644
--- a/services/core/java/com/android/server/protolog/common/InvalidFormatStringException.java
+++ b/core/java/com/android/internal/protolog/common/InvalidFormatStringException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.protolog.common;
+package com.android.internal.protolog.common;
/**
* Unsupported/invalid message format string error.
diff --git a/services/core/java/com/android/server/protolog/common/LogDataType.java b/core/java/com/android/internal/protolog/common/LogDataType.java
index e73b41abddc7..651932a7ba7e 100644
--- a/services/core/java/com/android/server/protolog/common/LogDataType.java
+++ b/core/java/com/android/internal/protolog/common/LogDataType.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.protolog.common;
+package com.android.internal.protolog.common;
import java.util.ArrayList;
import java.util.List;
diff --git a/services/core/java/com/android/server/protolog/common/ProtoLog.java b/core/java/com/android/internal/protolog/common/ProtoLog.java
index b631bcb23f5f..ab58d351d3b9 100644
--- a/services/core/java/com/android/server/protolog/common/ProtoLog.java
+++ b/core/java/com/android/internal/protolog/common/ProtoLog.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.protolog.common;
+package com.android.internal.protolog.common;
/**
* ProtoLog API - exposes static logging methods. Usage of this API is similar
diff --git a/core/java/com/android/internal/util/ScreenshotHelper.java b/core/java/com/android/internal/util/ScreenshotHelper.java
index 9bf05135c4c5..a23fc4b57b45 100644
--- a/core/java/com/android/internal/util/ScreenshotHelper.java
+++ b/core/java/com/android/internal/util/ScreenshotHelper.java
@@ -291,7 +291,7 @@ public class ScreenshotHelper {
};
Message msg = Message.obtain(null, screenshotType, screenshotRequest);
- final ServiceConnection myConn = mScreenshotConnection;
+
Handler h = new Handler(handler.getLooper()) {
@Override
public void handleMessage(Message msg) {
@@ -304,8 +304,8 @@ public class ScreenshotHelper {
break;
case SCREENSHOT_MSG_PROCESS_COMPLETE:
synchronized (mScreenshotLock) {
- if (myConn != null && mScreenshotConnection == myConn) {
- mContext.unbindService(myConn);
+ if (mScreenshotConnection != null) {
+ mContext.unbindService(mScreenshotConnection);
mScreenshotConnection = null;
mScreenshotService = null;
}
@@ -368,6 +368,7 @@ public class ScreenshotHelper {
}
} else {
Messenger messenger = new Messenger(mScreenshotService);
+
try {
messenger.send(msg);
} catch (RemoteException e) {
diff --git a/core/java/com/android/internal/util/StatLogger.java b/core/java/com/android/internal/util/StatLogger.java
index 29568d5020e3..2d65090ce51e 100644
--- a/core/java/com/android/internal/util/StatLogger.java
+++ b/core/java/com/android/internal/util/StatLogger.java
@@ -84,7 +84,7 @@ public class StatLogger {
* give it back to the {@link #logDurationStat(int, long)}} after the event.
*/
public long getTime() {
- return SystemClock.elapsedRealtimeNanos() / 1000;
+ return SystemClock.uptimeNanos() / 1000;
}
/**
diff --git a/core/jni/android_os_SystemClock.cpp b/core/jni/android_os_SystemClock.cpp
index b1f600053b9b..2fba445428f4 100644
--- a/core/jni/android_os_SystemClock.cpp
+++ b/core/jni/android_os_SystemClock.cpp
@@ -37,10 +37,12 @@ namespace android {
static_assert(std::is_same<int64_t, jlong>::value, "jlong isn't an int64_t");
static_assert(std::is_same<decltype(uptimeMillis()), int64_t>::value,
"uptimeMillis signature change, expected int64_t return value");
+static_assert(std::is_same<decltype(uptimeNanos()), int64_t>::value,
+ "uptimeNanos signature change, expected int64_t return value");
static_assert(std::is_same<decltype(elapsedRealtime()), int64_t>::value,
- "uptimeMillis signature change, expected int64_t return value");
+ "elapsedRealtime signature change, expected int64_t return value");
static_assert(std::is_same<decltype(elapsedRealtimeNano()), int64_t>::value,
- "uptimeMillis signature change, expected int64_t return value");
+ "elapsedRealtimeNano signature change, expected int64_t return value");
/*
* native public static long currentThreadTimeMillis();
@@ -76,6 +78,7 @@ static const JNINativeMethod gMethods[] = {
// All of these are @CriticalNative, so we can defer directly to SystemClock.h for
// some of these
{ "uptimeMillis", "()J", (void*) uptimeMillis },
+ { "uptimeNanos", "()J", (void*) uptimeNanos },
{ "elapsedRealtime", "()J", (void*) elapsedRealtime },
{ "elapsedRealtimeNanos", "()J", (void*) elapsedRealtimeNano },
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index d6a773fb91e0..85b4fe197980 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -116,7 +116,6 @@ static struct {
jfieldID width;
jfieldID height;
jfieldID useIdentityTransform;
- jfieldID rotation;
} gDisplayCaptureArgsClassInfo;
static struct {
@@ -325,8 +324,6 @@ static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env,
captureArgs.useIdentityTransform =
env->GetBooleanField(displayCaptureArgsObject,
gDisplayCaptureArgsClassInfo.useIdentityTransform);
- captureArgs.rotation = ui::toRotation(
- env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.rotation));
return captureArgs;
}
@@ -1849,8 +1846,6 @@ int register_android_view_SurfaceControl(JNIEnv* env)
GetFieldIDOrDie(env, displayCaptureArgsClazz, "mHeight", "I");
gDisplayCaptureArgsClassInfo.useIdentityTransform =
GetFieldIDOrDie(env, displayCaptureArgsClazz, "mUseIdentityTransform", "Z");
- gDisplayCaptureArgsClassInfo.rotation =
- GetFieldIDOrDie(env, displayCaptureArgsClazz, "mRotation", "I");
jclass layerCaptureArgsClazz =
FindClassOrDie(env, "android/view/SurfaceControl$LayerCaptureArgs");
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 1014fbb73877..0d65bd1cf9bb 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -744,6 +744,41 @@ enum Action {
// CATEGORY: SETTINGS
// OS: R
ACTION_CONFIRM_SIM_DELETION_OFF = 1739;
+
+ // ACTION: Settings > System > Gestures > Double tap > Toggle on Double tap
+ // CATEGORY: SETTINGS
+ // OS: S
+ ACTION_COLUMBUS_ENABLED = 1740;
+
+ // ACTION: Settings > System > Gestures > Double tap > Toggle off Double tap
+ // CATEGORY: SETTINGS
+ // OS: S
+ ACTION_COLUMBUS_DISABLED = 1741;
+
+ // ACTION: Settings > System > Gestures > Double tap > Invoke Assistant
+ // CATEGORY: SETTINGS
+ // OS: S
+ ACTION_COLUMBUS_ACTION_ASSISTANT = 1742;
+
+ // ACTION: Settings > System > Gestures > Double tap > Take screenshot
+ // CATEGORY: SETTINGS
+ // OS: S
+ ACTION_COLUMBUS_ACTION_SCREENSHOT = 1743;
+
+ // ACTION: Settings > System > Gestures > Double tap > Play and pause
+ // CATEGORY: SETTINGS
+ // OS: S
+ ACTION_COLUMBUS_ACTION_PLAY_PAUSE = 1744;
+
+ // ACTION: Settings > System > Gestures > Double tap > Open app overview
+ // CATEGORY: SETTINGS
+ // OS: S
+ ACTION_COLUMBUS_ACTION_OVERVIEW = 1745;
+
+ // ACTION: Settings > System > Gestures > Double tap > Open notification shade
+ // CATEGORY: SETTINGS
+ // OS: S
+ ACTION_COLUMBUS_ACTION_NOTIFICATION_SHADE = 1746;
}
/**
diff --git a/core/proto/android/app/tvsettings_enums.proto b/core/proto/android/app/tvsettings_enums.proto
index 31c5dd6b730a..4a3c59477f2f 100644
--- a/core/proto/android/app/tvsettings_enums.proto
+++ b/core/proto/android/app/tvsettings_enums.proto
@@ -168,7 +168,11 @@ enum ItemId {
// Google Assistant > Personal results (toggle)
ACCOUNT_SLICE_REG_ACCOUNT_ASSISTANT_PERSONAL_RESULTS = 0x12134000;
- // Reserving [0x12140000, 0x12190000] for possible future settings
+ // TvSettings > Account & Sign In (Slice) > [A regular account] >
+ // Apps only mode (toggle)
+ ACCOUNT_SLICE_REG_ACCOUNT_APPS_ONLY_MODE = 0x12140000;
+
+ // Reserving [0x12150000, 0x12190000] for possible future settings
// TvSettings > Account & Sign In (Slice) > [A regular account] > Remove
ACCOUNT_SLICE_REG_ACCOUNT_REMOVE = 0x121A0000;
diff --git a/core/proto/android/server/protolog.proto b/core/proto/android/internal/protolog.proto
index 34dc55b959c2..fee7a878f860 100644
--- a/core/proto/android/server/protolog.proto
+++ b/core/proto/android/internal/protolog.proto
@@ -16,7 +16,7 @@
syntax = "proto2";
-package com.android.server.protolog;
+package com.android.internal.protolog;
option java_multiple_files = true;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index fe290f3e97e8..edb972730f69 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1342,7 +1342,7 @@
android:priority="800" />
<!-- Allows an application to access data from sensors that the user uses to
- measure what is happening inside his/her body, such as heart rate.
+ measure what is happening inside their body, such as heart rate.
<p>Protection level: dangerous -->
<permission android:name="android.permission.BODY_SENSORS"
android:permissionGroup="android.permission-group.UNDEFINED"
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 2e4169e15c3b..4f55bf51c826 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -470,10 +470,10 @@
<string name="permdesc_wakeLock" product="tablet" msgid="2441742939101526277">"Permet que l\'aplicació impedeixi que la tauleta entri en repòs."</string>
<string name="permdesc_wakeLock" product="tv" msgid="2329298966735118796">"Permet que l\'aplicació impedeixi que el dispositiu Android TV entri en repòs."</string>
<string name="permdesc_wakeLock" product="default" msgid="3689523792074007163">"Permet que l\'aplicació impedeixi que el telèfon entri en repòs."</string>
- <string name="permlab_transmitIr" msgid="8077196086358004010">"transmissió d\'infraroigs"</string>
- <string name="permdesc_transmitIr" product="tablet" msgid="5884738958581810253">"Permet que l\'aplicació utilitzi el transmissor d\'infraroigs de la tauleta."</string>
- <string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"Permet que l\'aplicació faci servir el transmissor d\'infraroigs del dispositiu Android TV."</string>
- <string name="permdesc_transmitIr" product="default" msgid="8484193849295581808">"Permet que l\'aplicació utilitzi el transmissor d\'infraroigs del telèfon."</string>
+ <string name="permlab_transmitIr" msgid="8077196086358004010">"transmissió d\'infrarojos"</string>
+ <string name="permdesc_transmitIr" product="tablet" msgid="5884738958581810253">"Permet que l\'aplicació utilitzi el transmissor d\'infrarojos de la tauleta."</string>
+ <string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"Permet que l\'aplicació faci servir el transmissor d\'infrarojos del dispositiu Android TV."</string>
+ <string name="permdesc_transmitIr" product="default" msgid="8484193849295581808">"Permet que l\'aplicació utilitzi el transmissor d\'infrarojos del telèfon."</string>
<string name="permlab_setWallpaper" msgid="6959514622698794511">"establir fons de pantalla"</string>
<string name="permdesc_setWallpaper" msgid="2973996714129021397">"Permet que l\'aplicació estableixi el fons de pantalla del sistema."</string>
<string name="permlab_setWallpaperHints" msgid="1153485176642032714">"ajustament de la mida del fons de pantalla"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index fd7b1b2ab55a..bb79c2193a36 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1633,7 +1633,7 @@
<string name="accessibility_shortcut_menu_item_status_off" msgid="5531598275559472393">"निष्क्रिय"</string>
<string name="accessibility_enable_service_title" msgid="3931558336268541484">"<xliff:g id="SERVICE">%1$s</xliff:g> लाई तपाईंको यन्त्र पूर्ण रूपमा नियन्त्रण गर्न दिने हो?"</string>
<string name="accessibility_enable_service_encryption_warning" msgid="8603532708618236909">"तपाईंले <xliff:g id="SERVICE">%1$s</xliff:g> सक्रिय गर्नुभयो भने तपाईंको यन्त्रले डेटा इन्क्रिप्ट गर्ने सुविधाको स्तरोन्नति गर्न तपाईंको स्क्रिन लक सुविधाको प्रयोग गर्ने छैन।"</string>
- <string name="accessibility_service_warning_description" msgid="291674995220940133">"तपाईंलाई पहुँच राख्न आवश्यक पर्ने कुरामा सहयोग गर्ने अनुप्रयोगहरूमाथि पूर्ण नियन्त्रण गर्नु उपयुक्त हुन्छ तर अधिकांश अनुप्रयोगहरूका हकमा यस्तो नियन्त्रण उपयुक्त हुँदैन।"</string>
+ <string name="accessibility_service_warning_description" msgid="291674995220940133">"तपाईंलाई पहुँच राख्न आवश्यक पर्ने कुरामा सहयोग गर्ने एपमाथि पूर्ण नियन्त्रण गर्नु उपयुक्त हुन्छ तर अधिकांश अनुप्रयोगहरूका हकमा यस्तो नियन्त्रण उपयुक्त हुँदैन।"</string>
<string name="accessibility_service_screen_control_title" msgid="190017412626919776">"स्क्रिन हेर्नुहोस् र नियन्त्रण गर्नुहोस्"</string>
<string name="accessibility_service_screen_control_description" msgid="6946315917771791525">"यसले स्क्रिनमा देखिने सबै सामग्री पढ्न सक्छ र अन्य एपहरूमा उक्त सामग्री देखाउन सक्छ।"</string>
<string name="accessibility_service_action_perform_title" msgid="779670378951658160">"कारबाहीहरू हेर्नुहोस् र तिनमा कार्य गर्नुहोस्"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8913e8b18750..f99be880cbe3 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1823,6 +1823,8 @@
<string name="config_defaultCallScreening" translatable="false"></string>
<!-- The name of the package that will hold the system gallery role. -->
<string name="config_systemGallery" translatable="false">com.android.gallery3d</string>
+ <!-- The name of the package that will hold the system cluster service role. -->
+ <string name="config_systemAutomotiveCluster" translatable="false"></string>
<!-- The name of the package that will be allowed to change its components' label/icon. -->
<string name="config_overrideComponentUiPackage" translatable="false"></string>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 303fde6705c2..1e2d554a088b 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3069,7 +3069,8 @@
</public-group>
<public-group type="string" first-id="0x01040028">
- <!-- string definitions go here -->
+ <!-- @hide @SystemApi @TestApi -->
+ <public name="config_systemAutomotiveCluster" />
</public-group>
<public-group type="id" first-id="0x01020055">
diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml
index d8ec72f33ddc..166edca3d046 100644
--- a/core/res/res/xml/power_profile.xml
+++ b/core/res/res/xml/power_profile.xml
@@ -20,7 +20,7 @@
<device name="Android">
<!-- Most values are the incremental current used by a feature,
in mA (measured at nominal voltage).
- The default values are deliberately incorrect dummy values.
+ The default values are deliberately incorrect values.
OEM's must measure and provide actual values before
shipping a device.
Example real-world values are given in comments, but they
diff --git a/core/tests/coretests/src/android/app/WindowContextTest.java b/core/tests/coretests/src/android/app/WindowContextTest.java
index 630e16ac80d4..0f9bc4bee99a 100644
--- a/core/tests/coretests/src/android/app/WindowContextTest.java
+++ b/core/tests/coretests/src/android/app/WindowContextTest.java
@@ -30,7 +30,6 @@ import android.view.Display;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -47,7 +46,6 @@ import org.junit.runner.RunWith;
* <p>This test class is a part of Window Manager Service tests and specified in
* {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
*/
-@FlakyTest(bugId = 150812449, detail = "Remove after confirmed it's stable.")
@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index e0d702e98595..2bf9848304ad 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -24,6 +24,7 @@ import static android.app.servertransaction.TestUtils.resultInfoList;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import android.app.ContentProviderHolder;
import android.app.IApplicationThread;
import android.app.IInstrumentationWatcher;
import android.app.IUiAutomationConnection;
@@ -665,5 +666,10 @@ public class TransactionParcelTests {
public void performDirectAction(IBinder activityToken, String actionId, Bundle arguments,
RemoteCallback cancellationCallback, RemoteCallback resultCallback) {
}
+
+ @Override
+ public void notifyContentProviderPublishStatus(ContentProviderHolder holder, String auth,
+ int userId, boolean published) {
+ }
}
}
diff --git a/core/tests/coretests/src/android/app/timezonedetector/TimeZoneCapabilitiesTest.java b/core/tests/coretests/src/android/app/timezonedetector/TimeZoneCapabilitiesTest.java
index 8a36f1dc057b..72391f4d7dec 100644
--- a/core/tests/coretests/src/android/app/timezonedetector/TimeZoneCapabilitiesTest.java
+++ b/core/tests/coretests/src/android/app/timezonedetector/TimeZoneCapabilitiesTest.java
@@ -33,9 +33,11 @@ public class TimeZoneCapabilitiesTest {
public void testEquals() {
TimeZoneCapabilities.Builder builder1 = new TimeZoneCapabilities.Builder(ARBITRARY_USER_ID)
.setConfigureAutoDetectionEnabled(CAPABILITY_POSSESSED)
+ .setConfigureGeoDetectionEnabled(CAPABILITY_POSSESSED)
.setSuggestManualTimeZone(CAPABILITY_POSSESSED);
TimeZoneCapabilities.Builder builder2 = new TimeZoneCapabilities.Builder(ARBITRARY_USER_ID)
.setConfigureAutoDetectionEnabled(CAPABILITY_POSSESSED)
+ .setConfigureGeoDetectionEnabled(CAPABILITY_POSSESSED)
.setSuggestManualTimeZone(CAPABILITY_POSSESSED);
{
TimeZoneCapabilities one = builder1.build();
@@ -57,6 +59,20 @@ public class TimeZoneCapabilitiesTest {
assertEquals(one, two);
}
+ builder2.setConfigureGeoDetectionEnabled(CAPABILITY_NOT_ALLOWED);
+ {
+ TimeZoneCapabilities one = builder1.build();
+ TimeZoneCapabilities two = builder2.build();
+ assertNotEquals(one, two);
+ }
+
+ builder1.setConfigureGeoDetectionEnabled(CAPABILITY_NOT_ALLOWED);
+ {
+ TimeZoneCapabilities one = builder1.build();
+ TimeZoneCapabilities two = builder2.build();
+ assertEquals(one, two);
+ }
+
builder2.setSuggestManualTimeZone(CAPABILITY_NOT_ALLOWED);
{
TimeZoneCapabilities one = builder1.build();
@@ -76,12 +92,16 @@ public class TimeZoneCapabilitiesTest {
public void testParcelable() {
TimeZoneCapabilities.Builder builder = new TimeZoneCapabilities.Builder(ARBITRARY_USER_ID)
.setConfigureAutoDetectionEnabled(CAPABILITY_POSSESSED)
+ .setConfigureGeoDetectionEnabled(CAPABILITY_POSSESSED)
.setSuggestManualTimeZone(CAPABILITY_POSSESSED);
assertRoundTripParcelable(builder.build());
builder.setConfigureAutoDetectionEnabled(CAPABILITY_NOT_ALLOWED);
assertRoundTripParcelable(builder.build());
+ builder.setConfigureGeoDetectionEnabled(CAPABILITY_NOT_ALLOWED);
+ assertRoundTripParcelable(builder.build());
+
builder.setSuggestManualTimeZone(CAPABILITY_NOT_ALLOWED);
assertRoundTripParcelable(builder.build());
}
diff --git a/core/tests/coretests/src/android/app/timezonedetector/TimeZoneConfigurationTest.java b/core/tests/coretests/src/android/app/timezonedetector/TimeZoneConfigurationTest.java
index ac7e9c437b63..00dc73ed269f 100644
--- a/core/tests/coretests/src/android/app/timezonedetector/TimeZoneConfigurationTest.java
+++ b/core/tests/coretests/src/android/app/timezonedetector/TimeZoneConfigurationTest.java
@@ -29,8 +29,9 @@ public class TimeZoneConfigurationTest {
@Test
public void testBuilder_copyConstructor() {
- TimeZoneConfiguration.Builder builder1 =
- new TimeZoneConfiguration.Builder().setAutoDetectionEnabled(true);
+ TimeZoneConfiguration.Builder builder1 = new TimeZoneConfiguration.Builder()
+ .setAutoDetectionEnabled(true)
+ .setGeoDetectionEnabled(true);
TimeZoneConfiguration configuration1 = builder1.build();
TimeZoneConfiguration configuration2 =
@@ -41,16 +42,15 @@ public class TimeZoneConfigurationTest {
@Test
public void testIsComplete() {
- TimeZoneConfiguration incompleteConfiguration =
- new TimeZoneConfiguration.Builder()
- .build();
- assertFalse(incompleteConfiguration.isComplete());
+ TimeZoneConfiguration.Builder builder =
+ new TimeZoneConfiguration.Builder();
+ assertFalse(builder.build().isComplete());
- TimeZoneConfiguration completeConfiguration =
- new TimeZoneConfiguration.Builder()
- .setAutoDetectionEnabled(true)
- .build();
- assertTrue(completeConfiguration.isComplete());
+ builder.setAutoDetectionEnabled(true);
+ assertFalse(builder.build().isComplete());
+
+ builder.setGeoDetectionEnabled(true);
+ assertTrue(builder.build().isComplete());
}
@Test
@@ -122,6 +122,27 @@ public class TimeZoneConfigurationTest {
TimeZoneConfiguration two = builder2.build();
assertEquals(one, two);
}
+
+ builder1.setGeoDetectionEnabled(true);
+ {
+ TimeZoneConfiguration one = builder1.build();
+ TimeZoneConfiguration two = builder2.build();
+ assertNotEquals(one, two);
+ }
+
+ builder2.setGeoDetectionEnabled(false);
+ {
+ TimeZoneConfiguration one = builder1.build();
+ TimeZoneConfiguration two = builder2.build();
+ assertNotEquals(one, two);
+ }
+
+ builder1.setGeoDetectionEnabled(false);
+ {
+ TimeZoneConfiguration one = builder1.build();
+ TimeZoneConfiguration two = builder2.build();
+ assertEquals(one, two);
+ }
}
@Test
@@ -135,5 +156,11 @@ public class TimeZoneConfigurationTest {
builder.setAutoDetectionEnabled(false);
assertRoundTripParcelable(builder.build());
+
+ builder.setGeoDetectionEnabled(false);
+ assertRoundTripParcelable(builder.build());
+
+ builder.setGeoDetectionEnabled(true);
+ assertRoundTripParcelable(builder.build());
}
}
diff --git a/core/tests/coretests/src/android/view/WindowMetricsTest.java b/core/tests/coretests/src/android/view/WindowMetricsTest.java
index ddc977d380ae..96df9dda23c7 100644
--- a/core/tests/coretests/src/android/view/WindowMetricsTest.java
+++ b/core/tests/coretests/src/android/view/WindowMetricsTest.java
@@ -27,7 +27,6 @@ import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.platform.test.annotations.Presubmit;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -46,7 +45,6 @@ import org.junit.runner.RunWith;
* <p>This test class is a part of Window Manager Service tests and specified in
* {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
*/
-@FlakyTest(bugId = 148789183, detail = "Remove after confirmed it's stable.")
@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index 188ba9e0ca0e..96250db4aa51 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.os.Binder;
import android.os.Handler;
@@ -44,6 +45,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
@@ -493,7 +495,9 @@ public class BinderCallsStatsTest {
bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
PrintWriter pw = new PrintWriter(new StringWriter());
- bcs.dump(pw, new AppIdToPackageMap(new HashMap<>()), true);
+ bcs.dump(pw, new AppIdToPackageMap(new HashMap<>()), Process.INVALID_UID, true);
+
+ bcs.dump(pw, new AppIdToPackageMap(new HashMap<>()), WORKSOURCE_UID, true);
}
@Test
@@ -606,8 +610,8 @@ public class BinderCallsStatsTest {
assertEquals("-1", callStats.methodName);
assertEquals("com.android.internal.os.BinderCallsStats$OverflowBinder",
callStats.className);
- assertEquals(false , callStats.screenInteractive);
- assertEquals(-1 , callStats.callingUid);
+ assertEquals(false, callStats.screenInteractive);
+ assertEquals(-1, callStats.callingUid);
}
@Test
@@ -785,7 +789,7 @@ public class BinderCallsStatsTest {
bcs.time += 30;
bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
- for (Runnable runnable: mHandler.mRunnables) {
+ for (Runnable runnable : mHandler.mRunnables) {
// Execute all pending runnables. Ignore the delay.
runnable.run();
}
@@ -839,6 +843,53 @@ public class BinderCallsStatsTest {
assertEquals(3, tids[2]);
}
+ @Test
+ public void testTrackingSpecificWorksourceUid() {
+ mDeviceState.setCharging(true);
+
+ Binder binder = new Binder();
+
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.recordAllCallsForWorkSourceUid(WORKSOURCE_UID);
+
+ int[] transactions = {41, 42, 43, 42, 43, 43};
+ int[] durationsMs = {100, 200, 300, 400, 500, 600};
+
+ for (int i = 0; i < transactions.length; i++) {
+ CallSession callSession = bcs.callStarted(binder, transactions[i], WORKSOURCE_UID);
+ bcs.time += durationsMs[i];
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE, WORKSOURCE_UID);
+ }
+
+ BinderCallsStats.UidEntry uidEntry = bcs.getUidEntries().get(WORKSOURCE_UID);
+ Assert.assertNotNull(uidEntry);
+ assertEquals(6, uidEntry.callCount);
+
+ Collection<BinderCallsStats.CallStat> callStatsList = uidEntry.getCallStatsList();
+ assertEquals(3, callStatsList.size());
+ for (BinderCallsStats.CallStat callStat : callStatsList) {
+ switch (callStat.transactionCode) {
+ case 41:
+ assertEquals(1, callStat.callCount);
+ assertEquals(1, callStat.incrementalCallCount);
+ assertEquals(100, callStat.cpuTimeMicros);
+ break;
+ case 42:
+ assertEquals(2, callStat.callCount);
+ assertEquals(2, callStat.incrementalCallCount);
+ assertEquals(200 + 400, callStat.cpuTimeMicros);
+ break;
+ case 43:
+ assertEquals(3, callStat.callCount);
+ assertEquals(3, callStat.incrementalCallCount);
+ assertEquals(300 + 500 + 600, callStat.cpuTimeMicros);
+ break;
+ default:
+ fail("Unexpected transaction code: " + callStat.transactionCode);
+ }
+ }
+ }
+
private static class TestHandler extends Handler {
ArrayList<Runnable> mRunnables = new ArrayList<>();
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 2a8aa8c3e5b7..a11678189bad 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -238,12 +238,8 @@ EGLConfig EglManager::loadFP16Config(EGLDisplay display, SwapBehavior swapBehavi
return config;
}
-extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
-
void EglManager::initExtensions() {
auto extensions = StringUtils::split(eglQueryString(mEglDisplay, EGL_EXTENSIONS));
- auto extensionsAndroid =
- StringUtils::split(eglQueryStringImplementationANDROID(mEglDisplay, EGL_EXTENSIONS));
// For our purposes we don't care if EGL_BUFFER_AGE is a result of
// EGL_EXT_buffer_age or EGL_KHR_partial_update as our usage is covered
@@ -265,10 +261,7 @@ void EglManager::initExtensions() {
EglExtensions.surfacelessContext = extensions.has("EGL_KHR_surfaceless_context");
EglExtensions.fenceSync = extensions.has("EGL_KHR_fence_sync");
EglExtensions.waitSync = extensions.has("EGL_KHR_wait_sync");
-
- // EGL_ANDROID_native_fence_sync is not exposed to applications, so access
- // this through the private Android-specific query instead.
- EglExtensions.nativeFenceSync = extensionsAndroid.has("EGL_ANDROID_native_fence_sync");
+ EglExtensions.nativeFenceSync = extensions.has("EGL_ANDROID_native_fence_sync");
}
bool EglManager::hasEglContext() {
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 6e3fb1991acc..d4fb1be56890 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -147,6 +147,19 @@ public final class AudioDeviceInfo {
// {@link android.media.audiopolicy.AudioMix#ROUTE_FLAG_LOOP_BACK} flag.
public static final int TYPE_REMOTE_SUBMIX = 25;
+ /**
+ * A device type describing a Bluetooth Low Energy (BLE) audio headset or headphones.
+ * Headphones are grouped with headsets when the device is a sink:
+ * the features of headsets and headphones with regard to playback are the same.
+ */
+ public static final int TYPE_BLE_HEADSET = 26;
+
+ /**
+ * A device type describing a Bluetooth Low Energy (BLE) audio speaker.
+ */
+ public static final int TYPE_BLE_SPEAKER = 27;
+
+
/** @hide */
@IntDef(flag = false, prefix = "TYPE", value = {
TYPE_BUILTIN_EARPIECE,
@@ -171,7 +184,9 @@ public final class AudioDeviceInfo {
TYPE_HEARING_AID,
TYPE_BUILTIN_MIC,
TYPE_FM_TUNER,
- TYPE_TV_TUNER }
+ TYPE_TV_TUNER,
+ TYPE_BLE_HEADSET,
+ TYPE_BLE_SPEAKER}
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioDeviceType {}
@@ -193,7 +208,8 @@ public final class AudioDeviceInfo {
TYPE_LINE_ANALOG,
TYPE_LINE_DIGITAL,
TYPE_IP,
- TYPE_BUS }
+ TYPE_BUS,
+ TYPE_BLE_HEADSET}
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioDeviceTypeIn {}
@@ -219,7 +235,9 @@ public final class AudioDeviceInfo {
TYPE_AUX_LINE,
TYPE_IP,
TYPE_BUS,
- TYPE_HEARING_AID }
+ TYPE_HEARING_AID,
+ TYPE_BLE_HEADSET,
+ TYPE_BLE_SPEAKER}
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioDeviceTypeOut {}
@@ -248,7 +266,8 @@ public final class AudioDeviceInfo {
case TYPE_BUS:
case TYPE_HEARING_AID:
case TYPE_BUILTIN_SPEAKER_SAFE:
- case TYPE_REMOTE_SUBMIX:
+ case TYPE_BLE_HEADSET:
+ case TYPE_BLE_SPEAKER:
return true;
default:
return false;
@@ -275,6 +294,7 @@ public final class AudioDeviceInfo {
case TYPE_IP:
case TYPE_BUS:
case TYPE_REMOTE_SUBMIX:
+ case TYPE_BLE_HEADSET:
return true;
default:
return false;
@@ -527,6 +547,8 @@ public final class AudioDeviceInfo {
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_SPEAKER_SAFE,
TYPE_BUILTIN_SPEAKER_SAFE);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, TYPE_REMOTE_SUBMIX);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLE_HEADSET, TYPE_BLE_HEADSET);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_BLE_SPEAKER, TYPE_BLE_SPEAKER);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUILTIN_MIC, TYPE_BUILTIN_MIC);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET, TYPE_BLUETOOTH_SCO);
@@ -547,6 +569,7 @@ public final class AudioDeviceInfo {
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_IP, TYPE_IP);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUS, TYPE_BUS);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_REMOTE_SUBMIX, TYPE_REMOTE_SUBMIX);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLE_HEADSET, TYPE_BLE_HEADSET);
// privileges mapping to output device
EXT_TO_INT_DEVICE_MAPPING = new SparseIntArray();
@@ -576,6 +599,8 @@ public final class AudioDeviceInfo {
EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BUILTIN_SPEAKER_SAFE,
AudioSystem.DEVICE_OUT_SPEAKER_SAFE);
EXT_TO_INT_DEVICE_MAPPING.put(TYPE_REMOTE_SUBMIX, AudioSystem.DEVICE_OUT_REMOTE_SUBMIX);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_HEADSET, AudioSystem.DEVICE_OUT_BLE_HEADSET);
+ EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_SPEAKER, AudioSystem.DEVICE_OUT_BLE_SPEAKER);
}
}
diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java
index 42d0f0cc13c5..f6b04540c5c7 100644
--- a/media/java/android/media/AudioDevicePort.java
+++ b/media/java/android/media/AudioDevicePort.java
@@ -70,7 +70,9 @@ public class AudioDevicePort extends AudioPort {
* {@link AudioManager#DEVICE_IN_USB_DEVICE}) use an address composed of the ALSA card number
* and device number: "card=2;device=1"
* - Bluetooth devices ({@link AudioManager#DEVICE_OUT_BLUETOOTH_SCO},
- * {@link AudioManager#DEVICE_OUT_BLUETOOTH_SCO}, {@link AudioManager#DEVICE_OUT_BLUETOOTH_A2DP})
+ * {@link AudioManager#DEVICE_OUT_BLUETOOTH_SCO},
+ * {@link AudioManager#DEVICE_OUT_BLUETOOTH_A2DP}),
+ * {@link AudioManager#DEVICE_OUT_BLE_HEADSET}, {@link AudioManager#DEVICE_OUT_BLE_SPEAKER})
* use the MAC address of the bluetooth device in the form "00:11:22:AA:BB:CC" as reported by
* {@link BluetoothDevice#getAddress()}.
* - Deivces that do not have an address will indicate an empty string "".
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index e0da5d9deb7c..a16e063fe969 100755
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4530,6 +4530,18 @@ public class AudioManager {
*/
public static final int DEVICE_OUT_FM = AudioSystem.DEVICE_OUT_FM;
/** @hide
+ * The audio output device code for echo reference injection point.
+ */
+ public static final int DEVICE_OUT_ECHO_CANCELLER = AudioSystem.DEVICE_OUT_ECHO_CANCELLER;
+ /** @hide
+ * The audio output device code for a BLE audio headset.
+ */
+ public static final int DEVICE_OUT_BLE_HEADSET = AudioSystem.DEVICE_OUT_BLE_HEADSET;
+ /** @hide
+ * The audio output device code for a BLE audio speaker.
+ */
+ public static final int DEVICE_OUT_BLE_SPEAKER = AudioSystem.DEVICE_OUT_BLE_SPEAKER;
+ /** @hide
* This is not used as a returned value from {@link #getDevicesForStream}, but could be
* used in the future in a set method to select whatever default device is chosen by the
* platform-specific implementation.
@@ -4613,6 +4625,14 @@ public class AudioManager {
* The audio input device code for audio loopback
*/
public static final int DEVICE_IN_LOOPBACK = AudioSystem.DEVICE_IN_LOOPBACK;
+ /** @hide
+ * The audio input device code for an echo reference capture point.
+ */
+ public static final int DEVICE_IN_ECHO_REFERENCE = AudioSystem.DEVICE_IN_ECHO_REFERENCE;
+ /** @hide
+ * The audio input device code for a BLE audio headset.
+ */
+ public static final int DEVICE_IN_BLE_HEADSET = AudioSystem.DEVICE_IN_BLE_HEADSET;
/**
* Return true if the device code corresponds to an output device.
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index dbf25426a382..243ec1f1fcd0 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -867,6 +867,12 @@ public class AudioSystem
public static final int DEVICE_OUT_USB_HEADSET = 0x4000000;
/** @hide */
public static final int DEVICE_OUT_HEARING_AID = 0x8000000;
+ /** @hide */
+ public static final int DEVICE_OUT_ECHO_CANCELLER = 0x10000000;
+ /** @hide */
+ public static final int DEVICE_OUT_BLE_HEADSET = 0x20000000;
+ /** @hide */
+ public static final int DEVICE_OUT_BLE_SPEAKER = 0x20000001;
/** @hide */
public static final int DEVICE_OUT_DEFAULT = DEVICE_BIT_DEFAULT;
@@ -891,6 +897,8 @@ public class AudioSystem
public static final Set<Integer> DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET;
/** @hide */
public static final Set<Integer> DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET;
+ /** @hide */
+ public static final Set<Integer> DEVICE_OUT_ALL_BLE_SET;
static {
DEVICE_OUT_ALL_SET = new HashSet<>();
DEVICE_OUT_ALL_SET.add(DEVICE_OUT_EARPIECE);
@@ -921,6 +929,9 @@ public class AudioSystem
DEVICE_OUT_ALL_SET.add(DEVICE_OUT_PROXY);
DEVICE_OUT_ALL_SET.add(DEVICE_OUT_USB_HEADSET);
DEVICE_OUT_ALL_SET.add(DEVICE_OUT_HEARING_AID);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_ECHO_CANCELLER);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLE_HEADSET);
+ DEVICE_OUT_ALL_SET.add(DEVICE_OUT_BLE_SPEAKER);
DEVICE_OUT_ALL_SET.add(DEVICE_OUT_DEFAULT);
DEVICE_OUT_ALL_A2DP_SET = new HashSet<>();
@@ -946,6 +957,10 @@ public class AudioSystem
DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET = new HashSet<>();
DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET.addAll(DEVICE_OUT_ALL_HDMI_SYSTEM_AUDIO_SET);
DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER_SET.add(DEVICE_OUT_SPEAKER);
+
+ DEVICE_OUT_ALL_BLE_SET = new HashSet<>();
+ DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_HEADSET);
+ DEVICE_OUT_ALL_BLE_SET.add(DEVICE_OUT_BLE_SPEAKER);
}
// input devices
@@ -1020,6 +1035,8 @@ public class AudioSystem
/** @hide */
public static final int DEVICE_IN_ECHO_REFERENCE = DEVICE_BIT_IN | 0x10000000;
/** @hide */
+ public static final int DEVICE_IN_BLE_HEADSET = DEVICE_BIT_IN | 0x20000000;
+ /** @hide */
@UnsupportedAppUsage
public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT;
@@ -1057,6 +1074,7 @@ public class AudioSystem
DEVICE_IN_ALL_SET.add(DEVICE_IN_BLUETOOTH_BLE);
DEVICE_IN_ALL_SET.add(DEVICE_IN_HDMI_ARC);
DEVICE_IN_ALL_SET.add(DEVICE_IN_ECHO_REFERENCE);
+ DEVICE_IN_ALL_SET.add(DEVICE_IN_BLE_HEADSET);
DEVICE_IN_ALL_SET.add(DEVICE_IN_DEFAULT);
DEVICE_IN_ALL_SCO_SET = new HashSet<>();
@@ -1119,6 +1137,9 @@ public class AudioSystem
/** @hide */ public static final String DEVICE_OUT_PROXY_NAME = "proxy";
/** @hide */ public static final String DEVICE_OUT_USB_HEADSET_NAME = "usb_headset";
/** @hide */ public static final String DEVICE_OUT_HEARING_AID_NAME = "hearing_aid_out";
+ /** @hide */ public static final String DEVICE_OUT_ECHO_CANCELLER_NAME = "echo_canceller";
+ /** @hide */ public static final String DEVICE_OUT_BLE_HEADSET_NAME = "ble_headset";
+ /** @hide */ public static final String DEVICE_OUT_BLE_SPEAKER_NAME = "ble_speaker";
/** @hide */ public static final String DEVICE_IN_COMMUNICATION_NAME = "communication";
/** @hide */ public static final String DEVICE_IN_AMBIENT_NAME = "ambient";
@@ -1146,6 +1167,7 @@ public class AudioSystem
/** @hide */ public static final String DEVICE_IN_BLUETOOTH_BLE_NAME = "bt_ble";
/** @hide */ public static final String DEVICE_IN_ECHO_REFERENCE_NAME = "echo_reference";
/** @hide */ public static final String DEVICE_IN_HDMI_ARC_NAME = "hdmi_arc";
+ /** @hide */ public static final String DEVICE_IN_BLE_HEADSET_NAME = "ble_headset";
/** @hide */
@UnsupportedAppUsage
@@ -1208,6 +1230,12 @@ public class AudioSystem
return DEVICE_OUT_USB_HEADSET_NAME;
case DEVICE_OUT_HEARING_AID:
return DEVICE_OUT_HEARING_AID_NAME;
+ case DEVICE_OUT_ECHO_CANCELLER:
+ return DEVICE_OUT_ECHO_CANCELLER_NAME;
+ case DEVICE_OUT_BLE_HEADSET:
+ return DEVICE_OUT_BLE_HEADSET_NAME;
+ case DEVICE_OUT_BLE_SPEAKER:
+ return DEVICE_OUT_BLE_SPEAKER_NAME;
case DEVICE_OUT_DEFAULT:
default:
return Integer.toString(device);
@@ -1270,6 +1298,8 @@ public class AudioSystem
return DEVICE_IN_ECHO_REFERENCE_NAME;
case DEVICE_IN_HDMI_ARC:
return DEVICE_IN_HDMI_ARC_NAME;
+ case DEVICE_IN_BLE_HEADSET:
+ return DEVICE_IN_BLE_HEADSET_NAME;
case DEVICE_IN_DEFAULT:
default:
return Integer.toString(device);
diff --git a/media/java/android/media/MediaTranscodeManager.java b/media/java/android/media/MediaTranscodeManager.java
index e959e8e36b42..e1bff03f6833 100644
--- a/media/java/android/media/MediaTranscodeManager.java
+++ b/media/java/android/media/MediaTranscodeManager.java
@@ -225,13 +225,50 @@ public final class MediaTranscodeManager {
job.updateStatusAndResult(TranscodingJob.STATUS_FINISHED,
TranscodingJob.RESULT_ERROR);
- // Notifies client the job is done.
+ // Notifies client the job failed.
if (job.mListener != null && job.mListenerExecutor != null) {
job.mListenerExecutor.execute(() -> job.mListener.onTranscodingFinished(job));
}
}
}
+ private void handleTranscodingProgressUpdate(int jobId, int newProgress) {
+ synchronized (mPendingTranscodingJobs) {
+ // Gets the job associated with the jobId.
+ final TranscodingJob job = mPendingTranscodingJobs.get(jobId);
+
+ if (job == null) {
+ // This should not happen in reality.
+ Log.e(TAG, "Job " + jobId + " is not in PendingJobs");
+ return;
+ }
+
+ // Updates the job progress.
+ job.updateProgress(newProgress);
+
+ // Notifies client the progress update.
+ if (job.mProgressUpdateExecutor != null && job.mProgressUpdateListener != null) {
+ job.mProgressUpdateExecutor.execute(
+ () -> job.mProgressUpdateListener.onProgressUpdate(newProgress));
+ }
+ }
+ }
+
+ private void updateStatus(int jobId, int status) {
+ synchronized (mPendingTranscodingJobs) {
+ final TranscodingJob job = mPendingTranscodingJobs.get(jobId);
+
+ if (job == null) {
+ // This should not happen in reality.
+ Log.e(TAG, "Job " + jobId + " is not in PendingJobs");
+ return;
+ }
+
+ // Updates the job status.
+ job.updateStatus(status);
+ }
+ }
+
// Just forwards all the events to the event handler.
private ITranscodingClientCallback mTranscodingClientCallback =
new ITranscodingClientCallback.Stub() {
@@ -263,17 +300,17 @@ public final class MediaTranscodeManager {
@Override
public void onTranscodingStarted(int jobId) throws RemoteException {
-
+ updateStatus(jobId, TranscodingJob.STATUS_RUNNING);
}
@Override
public void onTranscodingPaused(int jobId) throws RemoteException {
-
+ updateStatus(jobId, TranscodingJob.STATUS_PAUSED);
}
@Override
public void onTranscodingResumed(int jobId) throws RemoteException {
-
+ updateStatus(jobId, TranscodingJob.STATUS_RUNNING);
}
@Override
@@ -294,8 +331,8 @@ public final class MediaTranscodeManager {
}
@Override
- public void onProgressUpdate(int jobId, int progress) throws RemoteException {
- //TODO(hkuang): Implement this.
+ public void onProgressUpdate(int jobId, int newProgress) throws RemoteException {
+ handleTranscodingProgressUpdate(jobId, newProgress);
}
};
@@ -661,11 +698,14 @@ public final class MediaTranscodeManager {
public static final int STATUS_RUNNING = 2;
/** The job is finished. */
public static final int STATUS_FINISHED = 3;
+ /** The job is paused. */
+ public static final int STATUS_PAUSED = 4;
@IntDef(prefix = { "STATUS_" }, value = {
STATUS_PENDING,
STATUS_RUNNING,
STATUS_FINISHED,
+ STATUS_PAUSED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface Status {}
@@ -821,17 +861,12 @@ public final class MediaTranscodeManager {
return mResult;
}
- private void setJobProgress(int newProgress) {
- synchronized (this) {
- mProgress = newProgress;
- }
+ private synchronized void updateProgress(int newProgress) {
+ mProgress = newProgress;
+ }
- // Notify listener.
- OnProgressUpdateListener onProgressUpdateListener = mProgressUpdateListener;
- if (mProgressUpdateListener != null) {
- mProgressUpdateExecutor.execute(
- () -> onProgressUpdateListener.onProgressUpdate(mProgress));
- }
+ private synchronized void updateStatus(int newStatus) {
+ mStatus = newStatus;
}
}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java
index 3a5e69293a02..8fe10888cab6 100644
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java
+++ b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java
@@ -33,10 +33,12 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
/*
* Functional tests for MediaTranscodeManager in the media framework.
@@ -230,5 +232,73 @@ public class MediaTranscodeManagerTest
30, TimeUnit.MILLISECONDS);
assertTrue("Fails to cancel transcoding", finishedOnTime);
}
+
+
+ @Test
+ public void testTranscodingProgressUpdate() throws Exception {
+ Log.d(TAG, "Starting: testMediaTranscodeManager");
+
+ Semaphore transcodeCompleteSemaphore = new Semaphore(0);
+ final CountDownLatch statusLatch = new CountDownLatch(1);
+
+ // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
+ // The full path of this file is:
+ // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
+ Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
+ + mContext.getCacheDir().getAbsolutePath() + "/HevcTranscode.mp4");
+
+ TranscodingRequest request =
+ new TranscodingRequest.Builder()
+ .setSourceUri(mSourceHEVCVideoUri)
+ .setDestinationUri(destinationUri)
+ .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
+ .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
+ .setVideoTrackFormat(createMediaFormat())
+ .build();
+ Executor listenerExecutor = Executors.newSingleThreadExecutor();
+
+ Log.i(TAG, "transcoding to " + createMediaFormat());
+
+ TranscodingJob job = mMediaTranscodeManager.enqueueRequest(request, listenerExecutor,
+ transcodingJob -> {
+ Log.d(TAG, "Transcoding completed with result: " + transcodingJob.getResult());
+ assertEquals(transcodingJob.getResult(), TranscodingJob.RESULT_SUCCESS);
+ transcodeCompleteSemaphore.release();
+ });
+ assertNotNull(job);
+
+ AtomicInteger progressUpdateCount = new AtomicInteger(0);
+
+ // Set progress update executor and use the same executor as result listener.
+ job.setOnProgressUpdateListener(listenerExecutor,
+ new TranscodingJob.OnProgressUpdateListener() {
+ int mPreviousProgress = 0;
+
+ @Override
+ public void onProgressUpdate(int newProgress) {
+ assertTrue("Invalid proress update", newProgress > mPreviousProgress);
+ assertTrue("Invalid proress update", newProgress <= 100);
+ if (newProgress > 0) {
+ statusLatch.countDown();
+ }
+ mPreviousProgress = newProgress;
+ progressUpdateCount.getAndIncrement();
+ Log.i(TAG, "Get progress update " + newProgress);
+ }
+ });
+
+ try {
+ statusLatch.await();
+ // The transcoding should not be finished yet as the clip is long.
+ assertTrue("Invalid status", job.getStatus() == TranscodingJob.STATUS_RUNNING);
+ } catch (InterruptedException e) { }
+
+ Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to cancel.");
+ boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
+ TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ assertTrue("Transcode failed to complete in time.", finishedOnTime);
+ assertTrue("Failed to receive at least 10 progress updates",
+ progressUpdateCount.get() > 10);
+ }
}
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index 70ef69d8ce72..0ba7f60c47c3 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -5596,6 +5596,7 @@ package android.app {
method public android.graphics.drawable.Icon getIcon();
method public android.app.RemoteInput[] getRemoteInputs();
method public int getSemanticAction();
+ method public boolean isAuthenticationRequired();
method public boolean isContextual();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.Notification.Action> CREATOR;
@@ -5625,6 +5626,7 @@ package android.app {
method @NonNull public android.app.Notification.Action.Builder extend(android.app.Notification.Action.Extender);
method @NonNull public android.os.Bundle getExtras();
method @NonNull public android.app.Notification.Action.Builder setAllowGeneratedReplies(boolean);
+ method @NonNull public android.app.Notification.Action.Builder setAuthenticationRequired(boolean);
method @NonNull public android.app.Notification.Action.Builder setContextual(boolean);
method @NonNull public android.app.Notification.Action.Builder setSemanticAction(int);
}
@@ -24047,6 +24049,8 @@ package android.media {
method public boolean isSink();
method public boolean isSource();
field public static final int TYPE_AUX_LINE = 19; // 0x13
+ field public static final int TYPE_BLE_HEADSET = 26; // 0x1a
+ field public static final int TYPE_BLE_SPEAKER = 27; // 0x1b
field public static final int TYPE_BLUETOOTH_A2DP = 8; // 0x8
field public static final int TYPE_BLUETOOTH_SCO = 7; // 0x7
field public static final int TYPE_BUILTIN_EARPIECE = 1; // 0x1
@@ -63863,7 +63867,7 @@ package java.lang.reflect {
package java.math {
- public class BigDecimal extends java.lang.Number implements java.lang.Comparable<java.math.BigDecimal> java.io.Serializable {
+ public class BigDecimal extends java.lang.Number implements java.lang.Comparable<java.math.BigDecimal> {
ctor public BigDecimal(char[], int, int);
ctor public BigDecimal(char[], int, int, java.math.MathContext);
ctor public BigDecimal(char[]);
@@ -63950,19 +63954,20 @@ package java.math {
field public static final java.math.BigDecimal ZERO;
}
- public class BigInteger extends java.lang.Number implements java.lang.Comparable<java.math.BigInteger> java.io.Serializable {
+ public class BigInteger extends java.lang.Number implements java.lang.Comparable<java.math.BigInteger> {
+ ctor public BigInteger(byte[]);
+ ctor public BigInteger(int, byte[]);
+ ctor public BigInteger(@NonNull String, int);
+ ctor public BigInteger(@NonNull String);
ctor public BigInteger(int, @NonNull java.util.Random);
ctor public BigInteger(int, int, @NonNull java.util.Random);
- ctor public BigInteger(@NonNull String);
- ctor public BigInteger(@NonNull String, int);
- ctor public BigInteger(int, byte[]);
- ctor public BigInteger(byte[]);
method @NonNull public java.math.BigInteger abs();
method @NonNull public java.math.BigInteger add(@NonNull java.math.BigInteger);
method @NonNull public java.math.BigInteger and(@NonNull java.math.BigInteger);
method @NonNull public java.math.BigInteger andNot(@NonNull java.math.BigInteger);
method public int bitCount();
method public int bitLength();
+ method public byte byteValueExact();
method @NonNull public java.math.BigInteger clearBit(int);
method public int compareTo(@NonNull java.math.BigInteger);
method @NonNull public java.math.BigInteger divide(@NonNull java.math.BigInteger);
@@ -63973,8 +63978,10 @@ package java.math {
method @NonNull public java.math.BigInteger gcd(@NonNull java.math.BigInteger);
method public int getLowestSetBit();
method public int intValue();
+ method public int intValueExact();
method public boolean isProbablePrime(int);
method public long longValue();
+ method public long longValueExact();
method @NonNull public java.math.BigInteger max(@NonNull java.math.BigInteger);
method @NonNull public java.math.BigInteger min(@NonNull java.math.BigInteger);
method @NonNull public java.math.BigInteger mod(@NonNull java.math.BigInteger);
@@ -63991,6 +63998,7 @@ package java.math {
method @NonNull public java.math.BigInteger setBit(int);
method @NonNull public java.math.BigInteger shiftLeft(int);
method @NonNull public java.math.BigInteger shiftRight(int);
+ method public short shortValueExact();
method public int signum();
method @NonNull public java.math.BigInteger subtract(@NonNull java.math.BigInteger);
method public boolean testBit(int);
diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt
index 86ac3e477dc4..35b483b9fb84 100644
--- a/non-updatable-api/module-lib-current.txt
+++ b/non-updatable-api/module-lib-current.txt
@@ -54,6 +54,7 @@ package android.os {
}
public interface Parcelable {
+ method public default int getStability();
field public static final int PARCELABLE_STABILITY_LOCAL = 0; // 0x0
field public static final int PARCELABLE_STABILITY_VINTF = 1; // 0x1
}
diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt
index 4d41fa5e3c4e..dbf9e9fb4ae5 100644
--- a/non-updatable-api/system-current.txt
+++ b/non-updatable-api/system-current.txt
@@ -301,6 +301,7 @@ package android {
field public static final int config_helpIntentNameKey = 17039390; // 0x104001e
field public static final int config_helpPackageNameKey = 17039387; // 0x104001b
field public static final int config_helpPackageNameValue = 17039388; // 0x104001c
+ field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
field public static final int config_systemGallery = 17039399; // 0x1040027
}
diff --git a/packages/CarSystemUI/proguard.flags b/packages/CarSystemUI/proguard.flags
index 66cbf2650429..516e70f56158 100644
--- a/packages/CarSystemUI/proguard.flags
+++ b/packages/CarSystemUI/proguard.flags
@@ -1,4 +1,6 @@
-keep class com.android.systemui.CarSystemUIFactory
-keep class com.android.car.notification.headsup.animationhelper.**
+-keep class com.android.systemui.CarGlobalRootComponent { *; }
+
-include ../SystemUI/proguard.flags
diff --git a/packages/CarSystemUI/samples/sample1/rro/Android.bp b/packages/CarSystemUI/samples/sample1/rro/Android.bp
new file mode 100644
index 000000000000..5b0347ff73fd
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample1/rro/Android.bp
@@ -0,0 +1,27 @@
+//
+// Copyright (C) 2020 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.
+//
+
+android_app {
+ name: "CarSystemUISampleOneRRO",
+ resource_dirs: ["res"],
+ certificate: "platform",
+ platform_apis: true,
+ manifest: "AndroidManifest.xml",
+ aaptflags: [
+ "--no-resource-deduping",
+ "--no-resource-removal",
+ ]
+} \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample1/rro/AndroidManifest.xml b/packages/CarSystemUI/samples/sample1/rro/AndroidManifest.xml
new file mode 100644
index 000000000000..5c25056f7915
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample1/rro/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.systemui.rro">
+ <overlay
+ android:targetPackage="com.android.systemui"
+ android:isStatic="false"
+ android:resourcesMap="@xml/car_sysui_overlays"
+ />
+</manifest> \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample1/rro/res/values/config.xml b/packages/CarSystemUI/samples/sample1/rro/res/values/config.xml
new file mode 100644
index 000000000000..854ab7d7e49b
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample1/rro/res/values/config.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources>
+ <!-- Configure which system bars should be displayed. -->
+ <bool name="config_enableTopNavigationBar">true</bool>
+ <bool name="config_enableLeftNavigationBar">true</bool>
+ <bool name="config_enableRightNavigationBar">true</bool>
+ <bool name="config_enableBottomNavigationBar">true</bool>
+
+ <!-- Configure the type of each system bar. Each system bar must have a unique type. -->
+ <!-- STATUS_BAR = 0-->
+ <!-- NAVIGATION_BAR = 1-->
+ <!-- STATUS_BAR_EXTRA = 2-->
+ <!-- NAVIGATION_BAR_EXTRA = 3-->
+ <integer name="config_topSystemBarType">0</integer>
+ <integer name="config_leftSystemBarType">2</integer>
+ <integer name="config_rightSystemBarType">3</integer>
+ <integer name="config_bottomSystemBarType">1</integer>
+
+ <!-- Configure the relative z-order among the system bars. When two system bars overlap (e.g.
+ if both top bar and left bar are enabled, it creates an overlapping space in the upper left
+ corner), the system bar with the higher z-order takes the overlapping space and padding is
+ applied to the other bar.-->
+ <!-- NOTE: If two overlapping system bars have the same z-order, SystemBarConfigs will throw a
+ RuntimeException, since their placing order cannot be determined. Bars that do not overlap
+ are allowed to have the same z-order. -->
+ <!-- NOTE: If the z-order of a bar is 10 or above, it will also appear on top of HUN's. -->
+ <integer name="config_topSystemBarZOrder">1</integer>
+ <integer name="config_leftSystemBarZOrder">0</integer>
+ <integer name="config_rightSystemBarZOrder">0</integer>
+ <integer name="config_bottomSystemBarZOrder">10</integer>
+</resources> \ No newline at end of file
diff --git a/packages/CarSystemUI/samples/sample1/rro/res/xml/car_sysui_overlays.xml b/packages/CarSystemUI/samples/sample1/rro/res/xml/car_sysui_overlays.xml
new file mode 100644
index 000000000000..7bcb8e1b43dd
--- /dev/null
+++ b/packages/CarSystemUI/samples/sample1/rro/res/xml/car_sysui_overlays.xml
@@ -0,0 +1,33 @@
+
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<overlay>
+ <item target="bool/config_enableTopNavigationBar" value="@bool/config_enableTopNavigationBar"/>
+ <item target="bool/config_enableLeftNavigationBar" value="@bool/config_enableLeftNavigationBar"/>
+ <item target="bool/config_enableRightNavigationBar" value="@bool/config_enableRightNavigationBar"/>
+ <item target="bool/config_enableBottomNavigationBar" value="@bool/config_enableBottomNavigationBar"/>
+
+ <item target="integer/config_topSystemBarType" value="@integer/config_topSystemBarType"/>
+ <item target="integer/config_leftSystemBarType" value="@integer/config_leftSystemBarType"/>
+ <item target="integer/config_rightSystemBarType" value="@integer/config_rightSystemBarType"/>
+ <item target="integer/config_bottomSystemBarType" value="@integer/config_bottomSystemBarType"/>
+
+ <item target="integer/config_topSystemBarZOrder" value="@integer/config_topSystemBarZOrder"/>
+ <item target="integer/config_leftSystemBarZOrder" value="@integer/config_leftSystemBarZOrder"/>
+ <item target="integer/config_rightSystemBarZOrder" value="@integer/config_rightSystemBarZOrder"/>
+ <item target="integer/config_bottomSystemBarZOrder" value="@integer/config_bottomSystemBarZOrder"/>
+</overlay> \ No newline at end of file
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java b/packages/CarSystemUI/src/com/android/systemui/CarGlobalRootComponent.java
index ece3bee000f9..fde0b1a97e46 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarGlobalRootComponent.java
@@ -18,9 +18,9 @@ package com.android.systemui;
import com.android.systemui.dagger.DependencyBinder;
import com.android.systemui.dagger.DependencyProvider;
+import com.android.systemui.dagger.GlobalRootComponent;
import com.android.systemui.dagger.SystemServicesModule;
import com.android.systemui.dagger.SystemUIModule;
-import com.android.systemui.dagger.SystemUIRootComponent;
import com.android.systemui.onehanded.dagger.OneHandedModule;
import com.android.systemui.pip.phone.dagger.PipModule;
@@ -28,6 +28,7 @@ import javax.inject.Singleton;
import dagger.Component;
+/** Car subclass for GlobalRootComponent. */
@Singleton
@Component(
modules = {
@@ -41,12 +42,15 @@ import dagger.Component;
CarSystemUIModule.class,
CarSystemUIBinder.class
})
-public interface CarSystemUIRootComponent extends SystemUIRootComponent {
+public interface CarGlobalRootComponent extends GlobalRootComponent {
/**
- * Builder for a CarSystemUIRootComponent.
+ * Builder for a CarGlobalRootComponent.
*/
@Component.Builder
- interface Builder extends SystemUIRootComponent.Builder {
- CarSystemUIRootComponent build();
+ interface Builder extends GlobalRootComponent.Builder {
+ CarGlobalRootComponent build();
}
+
+ @Override
+ CarSysUIComponent.Builder getSysUIComponent();
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java b/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java
new file mode 100644
index 000000000000..d19f368f22b6
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSysUIComponent.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+import com.android.systemui.dagger.SysUIComponent;
+import com.android.systemui.dagger.SysUISingleton;
+
+import dagger.Subcomponent;
+
+/**
+ * Dagger Subcomponent for Core SysUI.
+ */
+@SysUISingleton
+@Subcomponent(modules = {})
+public interface CarSysUIComponent extends SysUIComponent {
+
+ /**
+ * Builder for a CarSysUIComponent.
+ */
+ @Subcomponent.Builder
+ interface Builder extends SysUIComponent.Builder {
+ CarSysUIComponent build();
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
index 03ea9418415d..a65edc5477df 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
@@ -19,7 +19,7 @@ package com.android.systemui;
import android.content.Context;
import android.content.res.Resources;
-import com.android.systemui.dagger.SystemUIRootComponent;
+import com.android.systemui.dagger.GlobalRootComponent;
import java.util.HashSet;
import java.util.Set;
@@ -30,8 +30,8 @@ import java.util.Set;
public class CarSystemUIFactory extends SystemUIFactory {
@Override
- protected SystemUIRootComponent buildSystemUIRootComponent(Context context) {
- return DaggerCarSystemUIRootComponent.builder()
+ protected GlobalRootComponent buildGlobalRootComponent(Context context) {
+ return DaggerCarGlobalRootComponent.builder()
.context(context)
.build();
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index f4e704ea373e..53dd947a7eff 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -32,7 +32,7 @@ import com.android.systemui.car.keyguard.CarKeyguardViewController;
import com.android.systemui.car.statusbar.DozeServiceHost;
import com.android.systemui.car.statusbar.DummyNotificationShadeWindowController;
import com.android.systemui.car.volume.CarVolumeDialogComponent;
-import com.android.systemui.dagger.SystemUIRootComponent;
+import com.android.systemui.dagger.GlobalRootComponent;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
@@ -79,8 +79,15 @@ import dagger.Binds;
import dagger.Module;
import dagger.Provides;
-@Module(includes = {DividerModule.class, QSModule.class})
-public abstract class CarSystemUIModule {
+@Module(
+ includes = {
+ DividerModule.class,
+ QSModule.class
+ },
+ subcomponents = {
+ CarSysUIComponent.class
+ })
+abstract class CarSystemUIModule {
@Singleton
@Provides
@@ -188,8 +195,8 @@ public abstract class CarSystemUIModule {
abstract ShadeController provideShadeController(ShadeControllerImpl shadeController);
@Binds
- abstract SystemUIRootComponent bindSystemUIRootComponent(
- CarSystemUIRootComponent systemUIRootComponent);
+ abstract GlobalRootComponent bindGlobalRootComponent(
+ CarGlobalRootComponent globalRootComponent);
@Binds
abstract VolumeDialogComponent bindVolumeDialogComponent(
diff --git a/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java b/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
index 8efbad64f3d2..2c4545e7b265 100644
--- a/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
+++ b/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java
@@ -155,41 +155,6 @@ public class FusedLocationServiceTest {
assertThat(mManager.getNextLocation(TIMEOUT_MS)).isEqualTo(location);
}
- @Test
- public void testBypassRequest() throws Exception {
- LocationRequest request = LocationRequest.createFromDeprecatedProvider(FUSED_PROVIDER, 1000,
- 0, false).setQuality(LocationRequest.POWER_HIGH).setLocationSettingsIgnored(true);
-
- mProvider.setRequest(
- new ProviderRequest.Builder()
- .setInterval(1000)
- .setLocationSettingsIgnored(true)
- .setLocationRequests(Collections.singletonList(request))
- .build(),
- new WorkSource());
-
- boolean containsNetworkBypass = false;
- for (LocationRequest iRequest : mLocationManager.getTestProviderCurrentRequests(
- NETWORK_PROVIDER)) {
- if (iRequest.isLocationSettingsIgnored()) {
- containsNetworkBypass = true;
- break;
- }
- }
-
- boolean containsGpsBypass = false;
- for (LocationRequest iRequest : mLocationManager.getTestProviderCurrentRequests(
- GPS_PROVIDER)) {
- if (iRequest.isLocationSettingsIgnored()) {
- containsGpsBypass = true;
- break;
- }
- }
-
- assertThat(containsNetworkBypass).isTrue();
- assertThat(containsGpsBypass).isTrue();
- }
-
private static class LocationProviderManagerCapture extends ILocationProviderManager.Stub {
private final LinkedBlockingQueue<Location> mLocations;
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index ddf2bc0991a4..5f5be97c322c 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -165,7 +165,7 @@
<string name="tts_lang_not_selected" msgid="7927823081096056147">"Langue non sélectionnée"</string>
<string name="tts_default_lang_summary" msgid="9042620014800063470">"Définir la langue utilisée par la synthèse vocale"</string>
<string name="tts_play_example_title" msgid="1599468547216481684">"Écouter un échantillon"</string>
- <string name="tts_play_example_summary" msgid="634044730710636383">"Lire une courte démonstration de la synthèse vocale"</string>
+ <string name="tts_play_example_summary" msgid="634044730710636383">"Écoutez une courte démonstration de la synthèse vocale"</string>
<string name="tts_install_data_title" msgid="1829942496472751703">"Installer les données vocales"</string>
<string name="tts_install_data_summary" msgid="3608874324992243851">"Installer les données nécessaires à la synthèse vocale"</string>
<string name="tts_engine_security_warning" msgid="3372432853837988146">"Ce moteur de synthèse vocale est susceptible de collecter tout ce qui sera lu, y compris les données personnelles comme les mots de passe et les numéros de carte de paiement. Il provient du moteur <xliff:g id="TTS_PLUGIN_ENGINE_NAME">%s</xliff:g>. Voulez-vous activer son utilisation ?"</string>
@@ -189,8 +189,8 @@
<item msgid="1158955023692670059">"Rapide"</item>
<item msgid="5664310435707146591">"Plus rapide"</item>
<item msgid="5491266922147715962">"Très rapide"</item>
- <item msgid="7659240015901486196">"Rapide"</item>
- <item msgid="7147051179282410945">"Très rapide"</item>
+ <item msgid="7659240015901486196">"Beaucoup plus rapide"</item>
+ <item msgid="7147051179282410945">"Extrêmement rapide"</item>
<item msgid="581904787661470707">"La plus rapide"</item>
</string-array>
<string name="choose_profile" msgid="343803890897657450">"Sélectionner un profil"</string>
diff --git a/packages/Shell/src/com/android/shell/Screenshooter.java b/packages/Shell/src/com/android/shell/Screenshooter.java
index 8e0161961a49..85f25528f07e 100644
--- a/packages/Shell/src/com/android/shell/Screenshooter.java
+++ b/packages/Shell/src/com/android/shell/Screenshooter.java
@@ -17,11 +17,8 @@
package com.android.shell;
import android.graphics.Bitmap;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.hardware.display.DisplayManagerGlobal;
+import android.os.IBinder;
import android.util.Log;
-import android.view.Display;
import android.view.SurfaceControl;
/**
@@ -40,22 +37,17 @@ final class Screenshooter {
* @return The screenshot bitmap on success, null otherwise.
*/
static Bitmap takeScreenshot() {
- Display display = DisplayManagerGlobal.getInstance()
- .getRealDisplay(Display.DEFAULT_DISPLAY);
- Point displaySize = new Point();
- display.getRealSize(displaySize);
- final int displayWidth = displaySize.x;
- final int displayHeight = displaySize.y;
-
- int rotation = display.getRotation();
- Rect crop = new Rect(0, 0, displayWidth, displayHeight);
- Log.d(TAG, "Taking screenshot of dimensions " + displayWidth + " x " + displayHeight);
+ Log.d(TAG, "Taking fullscreen screenshot");
// Take the screenshot
- Bitmap screenShot =
- SurfaceControl.screenshot(crop, displayWidth, displayHeight, rotation);
+ final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
+ final SurfaceControl.DisplayCaptureArgs captureArgs =
+ new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
+ .build();
+ final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
+ SurfaceControl.captureDisplay(captureArgs);
+ final Bitmap screenShot = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
if (screenShot == null) {
- Log.e(TAG, "Failed to take screenshot of dimensions " + displayWidth + " x "
- + displayHeight);
+ Log.e(TAG, "Failed to take fullscreen screenshot");
return null;
}
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 14097b12e730..f24215791d1e 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -41,4 +41,6 @@
public <init>(android.content.Context);
}
--keep class com.android.wm.shell.* \ No newline at end of file
+-keep class com.android.wm.shell.*
+
+-keep class com.android.systemui.dagger.GlobalRootComponent { *; } \ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index 53eb2343d26a..401f3e3e0685 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -27,6 +27,7 @@
<item name="android:textColor">?attr/wallpaperTextColorSecondary</item>
<item name="android:textSize">14dp</item>
<item name="android:background">@drawable/kg_emergency_button_background</item>
+ <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="android:paddingLeft">12dp</item>
<item name="android:paddingRight">12dp</item>
</style>
diff --git a/packages/SystemUI/res/drawable-television/ic_volume_media.xml b/packages/SystemUI/res/drawable-television/ic_volume_media.xml
new file mode 100644
index 000000000000..e43c4b471db4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-television/ic_volume_media.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@color/tv_volume_dialog_accent"
+ android:pathData="M3,9v6h4l5,5L12,4L7,9L3,9zM16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02zM14,3.23v2.06c2.89,0.86 5,3.54 5,6.71s-2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77s-2.99,-7.86 -7,-8.77z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable-television/ic_volume_media_low.xml b/packages/SystemUI/res/drawable-television/ic_volume_media_low.xml
new file mode 100644
index 000000000000..0f6dc9517f53
--- /dev/null
+++ b/packages/SystemUI/res/drawable-television/ic_volume_media_low.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@color/tv_volume_dialog_accent"
+ android:pathData="M3,15V9H7L12,4V20L7,15H3ZM14,7.97C15.48,8.71 16.5,10.23 16.5,12C16.5,13.77 15.48,15.29 14,16.02V7.97Z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable-television/ic_volume_media_mute.xml b/packages/SystemUI/res/drawable-television/ic_volume_media_mute.xml
new file mode 100644
index 000000000000..4b59e13516d2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-television/ic_volume_media_mute.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@color/tv_volume_dialog_accent"
+ android:pathData="M16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v2.21l2.45,2.45c0.03,-0.2 0.05,-0.41 0.05,-0.63zM19,12c0,0.94 -0.2,1.82 -0.54,2.64l1.51,1.51C20.63,14.91 21,13.5 21,12c0,-4.28 -2.99,-7.86 -7,-8.77v2.06c2.89,0.86 5,3.54 5,6.71zM4.27,3L3,4.27 7.73,9L3,9v6h4l5,5v-6.73l4.25,4.25c-0.67,0.52 -1.42,0.93 -2.25,1.18v2.06c1.38,-0.31 2.63,-0.95 3.69,-1.81L19.73,21 21,19.73l-9,-9L4.27,3zM12,4L9.91,6.09 12,8.18L12,4z"/>
+</vector>
+
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_low.xml b/packages/SystemUI/res/drawable/ic_volume_media_low.xml
new file mode 100644
index 000000000000..87591de39d54
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_volume_media_low.xml
@@ -0,0 +1,18 @@
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@drawable/ic_volume_media" />
+</selector>
diff --git a/packages/SystemUI/res/drawable/tv_ring_white.xml b/packages/SystemUI/res/drawable/tv_rect_shadow_rounded.xml
index 0f7cc1082f71..93f8724b22a9 100644
--- a/packages/SystemUI/res/drawable/tv_ring_white.xml
+++ b/packages/SystemUI/res/drawable/tv_rect_shadow_rounded.xml
@@ -16,10 +16,10 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
+ android:shape="rectangle">
- <stroke
- android:width="1dp"
- android:color="@android:color/white" />
+ <corners android:radius="20dp"/>
+ <solid android:color="@color/tv_audio_recording_indicator_icon_background"/>
+ <stroke android:width="1dp" android:color="@color/tv_audio_recording_indicator_stroke"/>
</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/tv_circle_dark.xml b/packages/SystemUI/res/drawable/tv_volume_dialog_background.xml
index d1ba8e71ec31..fee6e57d2e86 100644
--- a/packages/SystemUI/res/drawable/tv_circle_dark.xml
+++ b/packages/SystemUI/res/drawable/tv_volume_dialog_background.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2019 The Android Open Source Project
+ ~ Copyright (C) 2020 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.
@@ -16,9 +16,9 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
+ android:shape="rectangle">
- <solid
- android:color="@color/tv_audio_recording_indicator_background" />
+ <solid android:color="@color/tv_volume_dialog_background" />
+ <corners android:radius="@dimen/tv_volume_dialog_corner_radius"/>
-</shape> \ No newline at end of file
+</shape>
diff --git a/packages/SystemUI/res/drawable/tv_circle_white_translucent.xml b/packages/SystemUI/res/drawable/tv_volume_dialog_circle.xml
index 55d21de00ca3..3c4fc05914f8 100644
--- a/packages/SystemUI/res/drawable/tv_circle_white_translucent.xml
+++ b/packages/SystemUI/res/drawable/tv_volume_dialog_circle.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2019 The Android Open Source Project
+ ~ Copyright (C) 2020 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.
@@ -17,8 +17,6 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
+ <solid android:color="@color/tv_volume_dialog_circle" />
- <solid
- android:color="@color/tv_audio_recording_indicator_pulse" />
-
-</shape> \ No newline at end of file
+</shape>
diff --git a/packages/SystemUI/res/layout-land-television/volume_dialog.xml b/packages/SystemUI/res/layout-land-television/volume_dialog.xml
index e0d158d757b3..56d847c6aa2e 100644
--- a/packages/SystemUI/res/layout-land-television/volume_dialog.xml
+++ b/packages/SystemUI/res/layout-land-television/volume_dialog.xml
@@ -20,7 +20,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
- android:theme="@style/qs_theme">
+ android:theme="@style/volume_dialog_theme">
<FrameLayout
android:id="@+id/volume_dialog"
@@ -46,7 +46,7 @@
android:translationZ="@dimen/volume_dialog_elevation"
android:clipChildren="false"
android:clipToPadding="false"
- android:background="@drawable/rounded_bg_full">
+ android:background="@drawable/tv_volume_dialog_background">
<LinearLayout
android:id="@+id/volume_dialog_rows"
@@ -54,9 +54,7 @@
android:layout_height="wrap_content"
android:minWidth="@dimen/volume_dialog_panel_width"
android:gravity="center"
- android:orientation="horizontal"
- android:paddingRight="@dimen/volume_dialog_stream_padding"
- android:paddingLeft="@dimen/volume_dialog_stream_padding">
+ android:orientation="horizontal">
<!-- volume rows added and removed here! :-) -->
</LinearLayout>
@@ -98,4 +96,4 @@
</FrameLayout>
-</FrameLayout> \ No newline at end of file
+</FrameLayout>
diff --git a/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml b/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml
index 08209ab09169..c0f0aa8bbc8d 100644
--- a/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml
@@ -21,11 +21,12 @@
android:background="@android:color/transparent"
android:clipChildren="false"
android:clipToPadding="false"
- android:theme="@style/qs_theme">
+ android:theme="@style/volume_dialog_theme">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
+ android:padding="@dimen/tv_volume_dialog_row_padding"
android:background="@android:color/transparent"
android:gravity="center"
android:layout_gravity="center"
@@ -33,9 +34,9 @@
<com.android.keyguard.AlphaOptimizedImageButton
android:id="@+id/volume_row_icon"
style="@style/VolumeButtons"
- android:layout_width="@dimen/volume_dialog_tap_target_size"
- android:layout_height="@dimen/volume_dialog_tap_target_size"
- android:background="@drawable/ripple_drawable_20dp"
+ android:layout_width="@dimen/tv_volume_dialog_bubble_size"
+ android:layout_height="@dimen/tv_volume_dialog_bubble_size"
+ android:background="@drawable/tv_volume_dialog_circle"
android:tint="@color/accent_tint_color_selector"
android:soundEffectsEnabled="false" />
<TextView
@@ -62,6 +63,15 @@
android:layout_gravity="center"
android:rotation="0" />
</FrameLayout>
+ <TextView
+ android:id="@+id/volume_number"
+ android:layout_width="@dimen/tv_volume_dialog_bubble_size"
+ android:layout_height="@dimen/tv_volume_dialog_bubble_size"
+ android:maxLength="2"
+ android:gravity="center"
+ android:background="@drawable/tv_volume_dialog_circle"
+ android:textSize="@dimen/tv_volume_number_text_size"
+ android:textColor="@color/accent_tint_color_selector"/>
</LinearLayout>
<include layout="@layout/volume_dnd_icon"/>
diff --git a/packages/SystemUI/res/layout-land/volume_dialog.xml b/packages/SystemUI/res/layout-land/volume_dialog.xml
index 5da7819c3d76..c420117073c5 100644
--- a/packages/SystemUI/res/layout-land/volume_dialog.xml
+++ b/packages/SystemUI/res/layout-land/volume_dialog.xml
@@ -22,7 +22,7 @@
android:gravity="right"
android:layout_gravity="right"
android:background="@android:color/transparent"
- android:theme="@style/qs_theme">
+ android:theme="@style/volume_dialog_theme">
<FrameLayout
android:id="@+id/volume_dialog"
diff --git a/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml b/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
index 1d2340dadb8a..f9336a540376 100644
--- a/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
+++ b/packages/SystemUI/res/layout/tv_audio_recording_indicator.xml
@@ -19,7 +19,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
- android:padding="32dp">
+ android:padding="12dp">
<FrameLayout
android:layout_width="wrap_content"
@@ -32,45 +32,25 @@
android:orientation="horizontal">
<FrameLayout
- android:layout_width="45dp"
- android:layout_height="47dp">
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent">
<View
android:id="@+id/icon_container_bg"
- android:layout_width="match_parent"
+ android:layout_width="50dp"
android:layout_height="match_parent"
android:background="@drawable/tv_rect_dark_left_rounded"/>
<FrameLayout
android:id="@+id/icon_mic"
- android:layout_width="35dp"
- android:layout_height="35dp"
- android:layout_marginStart="6dp"
- android:layout_marginTop="6dp"
- android:layout_marginBottom="6dp">
-
- <View
- android:layout_width="27dp"
- android:layout_height="27dp"
- android:layout_gravity="center"
- android:background="@drawable/tv_circle_dark"/>
-
- <ImageView
- android:id="@+id/pulsating_circle"
- android:layout_width="27dp"
- android:layout_height="27dp"
- android:layout_gravity="center"
- android:background="@drawable/tv_circle_white_translucent"/>
-
- <ImageView
- android:layout_width="27dp"
- android:layout_height="27dp"
- android:layout_gravity="center"
- android:src="@drawable/tv_ring_white"/>
+ android:layout_width="34dp"
+ android:layout_height="24dp"
+ android:layout_gravity="center"
+ android:background="@drawable/tv_rect_shadow_rounded">
<ImageView
- android:layout_width="16dp"
- android:layout_height="16dp"
+ android:layout_width="13dp"
+ android:layout_height="13dp"
android:layout_gravity="center"
android:background="@drawable/tv_ic_mic_white"/>
</FrameLayout>
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index 7d6547b9cd42..a90b1eb471ff 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -22,7 +22,7 @@
android:gravity="right"
android:layout_gravity="right"
android:background="@android:color/transparent"
- android:theme="@style/qs_theme">
+ android:theme="@style/volume_dialog_theme">
<!-- right-aligned to be physically near volume button -->
<LinearLayout
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index 6128da8627a9..b9efc5be70c1 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -20,7 +20,7 @@
android:layout_width="@dimen/volume_dialog_panel_width"
android:clipChildren="false"
android:clipToPadding="false"
- android:theme="@style/qs_theme">
+ android:theme="@style/volume_dialog_theme">
<LinearLayout
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index ee8700261db5..bac915d854d8 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Laai tans aanbevelings"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Versteek die huidige sessie."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Versteek"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Maak toe"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Hervat"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Instellings"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Onaktief, gaan program na"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 03eb39659ef3..aedbded46298 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ምክሮችን በመጫን ላይ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"ሚዲያ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"የአሁኑን ክፍለ-ጊዜ ደብቅ።"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ደብቅ"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"ከቆመበት ቀጥል"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ቅንብሮች"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ንቁ ያልኾነ፣ መተግበሪያን ይፈትሹ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 95d54a2386dd..fee86ca42fe6 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -1093,7 +1093,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"جارٍ تحميل الاقتراحات"</string>
<string name="controls_media_title" msgid="1746947284862928133">"الوسائط"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"إخفاء الجلسة الحالية"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"إخفاء"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"استئناف التشغيل"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"الإعدادات"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"غير نشط، تحقّق من التطبيق."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 3023a27b15b4..3778df80197b 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"চুপাৰিছসমূহ ল’ড কৰি থকা হৈছে"</string>
<string name="controls_media_title" msgid="1746947284862928133">"মিডিয়া"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"বৰ্তমানৰ ছেশ্বনটো লুকুৱাওক।"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"লুকুৱাওক"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"পুনৰ আৰম্ভ কৰক"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ছেটিংসমূহ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"সক্ৰিয় নহয়, এপ্‌টো পৰীক্ষা কৰক"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 3c8e04b7ba35..874bf7465827 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Tövsiyələr yüklənir"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Cari sessiyanı gizlədin."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Gizlədin"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Davam edin"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ayarlar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Aktiv deyil, tətbiqi yoxlayın"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 4b400eb479c9..2a120c57e955 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -1075,7 +1075,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavaju se preporuke"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Sakrijte aktuelnu sesiju."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sakrij"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Podešavanja"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno. Vidite aplikaciju"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index f1064fb7b1d7..e4bb67ae65c6 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Загружаюцца рэкамендацыі"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Мультымедыя"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Схаваць цяперашні сеанс."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Схаваць"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Узнавіць"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Налады"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактыўна, праверце праграму"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 8ba2a1e51769..c51e58ccd6cf 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Препоръките се зареждат"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Мултимедия"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Скриване на текущата сесия."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Скриване"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Възобновяване"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Настройки"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, проверете прилож."</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 5861c44c1cbb..3d00ca858ef5 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"সাজেশন লোড করা হচ্ছে"</string>
<string name="controls_media_title" msgid="1746947284862928133">"মিডিয়া"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"বর্তমান সেশন লুকান।"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"লুকান"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"আবার চালু করুন"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"সেটিংস"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"বন্ধ আছে, অ্যাপ চেক করুন"</string>
@@ -1084,8 +1085,6 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"নতুন কন্ট্রোল দেখতে পাওয়ার বোতাম টিপে ধরে থাকুন"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"কন্ট্রোল যোগ করুন"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"কন্ট্রোল এডিট করুন"</string>
- <!-- no translation found for one_handed_tutorial_title (6312198435090726656) -->
- <skip />
- <!-- no translation found for one_handed_tutorial_description (7674850272340517174) -->
- <skip />
+ <string name="one_handed_tutorial_title" msgid="6312198435090726656">"\'এক হাতে ব্যবহার করার মোড\'-এর ব্যবহার"</string>
+ <string name="one_handed_tutorial_description" msgid="7674850272340517174">"বেরিয়ে আসার জন্য, স্ক্রিনের নিচ থেকে উপরের দিকে সোয়াইপ করুন অথবা অ্যাপের আইকনের উপরে যেকোনও জায়গায় ট্যাপ করুন"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 984cbebd42eb..14259840d503 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -1075,7 +1075,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavanje preporuka"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Sakrijte trenutnu sesiju."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sakrij"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Postavke"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, vidite aplikaciju"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index b8c41efa7813..b1501558f924 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregant les recomanacions"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimèdia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Amaga la sessió actual."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Amaga"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Reprèn"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configuració"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactiu; comprova l\'aplicació"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index f946cc4f9552..ae6cc13cd1df 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Načítání doporučení"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Média"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Skrýt aktuální relaci."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skrýt"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Pokračovat"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavení"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivní, zkontrolujte aplikaci"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index a6de8a618f23..09f7f1a8762e 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Indlæser anbefalinger"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Medie"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Skjul den aktuelle session."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skjul"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Genoptag"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Indstillinger"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Tjek appen"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 372cc1166fce..2410e4785c8d 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Empfehlungen werden geladen"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Medien"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Du kannst die aktuelle Sitzung ausblenden."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ausblenden"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Fortsetzen"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Einstellungen"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv – sieh in der App nach"</string>
@@ -1084,8 +1085,6 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"Zum Anzeigen der Karten für neue Geräte Ein-/Aus-Taste gedrückt halten"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"Steuerelemente hinzufügen"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Steuerelemente bearbeiten"</string>
- <!-- no translation found for one_handed_tutorial_title (6312198435090726656) -->
- <skip />
- <!-- no translation found for one_handed_tutorial_description (7674850272340517174) -->
- <skip />
+ <string name="one_handed_tutorial_title" msgid="6312198435090726656">"Einhandmodus verwenden"</string>
+ <string name="one_handed_tutorial_description" msgid="7674850272340517174">"Wenn du die App schließen möchtest, wische vom unteren Rand des Displays nach oben oder tippe auf eine beliebige Stelle oberhalb der App"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index b4673476bad5..f66c5a88b102 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Φόρτωση προτάσεων"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Μέσα"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Απόκρυψη της τρέχουσας περιόδου λειτουργίας."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Απόκρυψη"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Συνέχιση"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ρυθμίσεις"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Ανενεργό, έλεγχος εφαρμογής"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 7fa7f83c5f12..0e22b583352c 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index f73dad3a8bef..acf087d51181 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 7fa7f83c5f12..0e22b583352c 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 7fa7f83c5f12..0e22b583352c 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Hide the current session."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Hide"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dismiss"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Settings"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 6140bf1eea3d..4f4238a5eb45 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‎‏‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‏‎‎‎‏‎‎‏‎‎‎‏‎‏‎‏‎‎‎Loading recommendations‎‏‎‎‏‎"</string>
<string name="controls_media_title" msgid="1746947284862928133">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‎‎‏‏‏‎‎‏‎‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‏‎‏‎Media‎‏‎‎‏‎"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‎‏‎‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎Hide the current session.‎‏‎‎‏‎"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‏‎‏‏‎‏‎‎‏‏‎‏‎‏‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎Hide‎‏‎‎‏‎"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‎‏‎‎‏‎‏‎‎‎‏‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‎‏‎Dismiss‎‏‎‎‏‎"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‏‎‏‎‏‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎‎‏‏‏‎‎‎‎‏‎‏‎Resume‎‏‎‎‏‎"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‏‏‎‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‏‏‎‎‎‎Settings‎‏‎‎‏‎"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎‏‏‏‏‏‏‎‎Inactive, check app‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 6818116ec9b5..45e072496b25 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendaciones"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Contenido multimedia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Oculta la sesión actual."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Reanudar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configuración"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Verifica la app"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index f09a0d24b26e..f7ebbd02708a 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendaciones"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimedia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ocultar la sesión."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Reanudar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ajustes"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo, comprobar aplicación"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 6236f251f55d..1e5e49e0a143 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Soovituste laadimine"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Meedia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Peidetakse praegune seanss."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Peida"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Jätka"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Seaded"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Passiivne, vaadake rakendust"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 167a09c71ce3..38b2103d7973 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Gomendioak kargatzen"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimedia-edukia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ezkutatu uneko saioa."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ezkutatu"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Baztertu"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Berrekin"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ezarpenak"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktibo; egiaztatu aplikazioa"</string>
@@ -1085,5 +1085,5 @@
<string name="controls_menu_add" msgid="4447246119229920050">"Gehitu aukerak"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"Editatu aukerak"</string>
<string name="one_handed_tutorial_title" msgid="6312198435090726656">"Esku bakarreko modua erabiltzea"</string>
- <string name="one_handed_tutorial_description" msgid="7674850272340517174">"Ateratzeko, pasatu hatza pantailaren behealdetik gora edo sakatu aplikazioaren gainean, edonon"</string>
+ <string name="one_handed_tutorial_description" msgid="7674850272340517174">"Ateratzeko, pasatu hatza pantailaren behealdetik gora edo sakatu aplikazioaren gainaldea"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 055505200cc2..d39d0c3d5027 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"درحال بار کردن توصیه‌ها"</string>
<string name="controls_media_title" msgid="1746947284862928133">"رسانه"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"جلسه فعلی پنهان شود."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"پنهان کردن"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"رد کردن"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ازسرگیری"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"تنظیمات"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"غیرفعال، برنامه را بررسی کنید"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index ec9bbc4a8929..fa076c4fc40e 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Ladataan suosituksia"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Piilota nykyinen käyttökerta."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Piilota"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Jatka"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Asetukset"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Epäaktiivinen, tarkista sovellus"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 6c5387f63eda..9c418f79a075 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Chargement des recommandations…"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Commandes multimédias"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Masquer la session en cours."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Masquer"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Reprendre"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Paramètres"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifiez l\'appli"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 3a2ae07bc64d..3e2f5fdbff1d 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Chargement des recommandations"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimédia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Masquer la session en cours."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Masquer"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Reprendre"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Paramètres"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifier l\'appli"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 25c7b4bfab59..9ecd75e80a4c 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendacións"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Contido multimedia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Oculta a sesión actual."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configuración"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Comproba a app"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 17cc5a45aeb9..6e05a540a13e 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"સુઝાવ લોડ કરી રહ્યાં છીએ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"મીડિયા"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"હાલનું સત્ર છુપાવો."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"છુપાવો"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"ફરી શરૂ કરો"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"સેટિંગ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"નિષ્ક્રિય, ઍપને ચેક કરો"</string>
@@ -1084,8 +1085,6 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"નવા નિયંત્રણ જોવા માટે પાવર બટનને દબાવી રાખો"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"નિયંત્રણો ઉમેરો"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"નિયંત્રણોમાં ફેરફાર કરો"</string>
- <!-- no translation found for one_handed_tutorial_title (6312198435090726656) -->
- <skip />
- <!-- no translation found for one_handed_tutorial_description (7674850272340517174) -->
- <skip />
+ <string name="one_handed_tutorial_title" msgid="6312198435090726656">"એક-હાથે વાપરો મોડનો ઉપયોગ કરી રહ્યાં છીએ"</string>
+ <string name="one_handed_tutorial_description" msgid="7674850272340517174">"બહાર નીકળવા માટે, સ્ક્રીનની નીચેના ભાગથી ઉપરની તરફ સ્વાઇપ કરો અથવા ઍપના આઇકન પર ગમે ત્યાં ટૅપ કરો"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 97ae7b6e8926..de4fc482a101 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -1071,7 +1071,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"सुझाव लोड हो रहे हैं"</string>
<string name="controls_media_title" msgid="1746947284862928133">"मीडिया"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"इस मीडिया सेशन को छिपाएं."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"छिपाएं"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"खारिज करें"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"फिर से शुरू करें"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिंग"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"काम नहीं कर रहा, ऐप जांचें"</string>
@@ -1086,6 +1086,6 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"नए कंट्रोल देखने के लिए पावर बटन दबाकर रखें"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"कंट्राेल जोड़ें"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"कंट्रोल मेन्यू में बदलाव करें"</string>
- <string name="one_handed_tutorial_title" msgid="6312198435090726656">"वन-हैंडेड मोड का इस्तेमाल करें"</string>
+ <string name="one_handed_tutorial_title" msgid="6312198435090726656">"वन-हैंडेड मोड का इस्तेमाल करना"</string>
<string name="one_handed_tutorial_description" msgid="7674850272340517174">"इसे बंद करने के लिए, स्क्रीन के सबसे निचले हिस्से से ऊपर की ओर स्वाइप करें या ऐप्लिकेशन के आइकॉन के ऊपर कहीं भी टैप करें"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 9e17735ef18d..4bebe79c3c44 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -1075,7 +1075,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavanje preporuka"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Mediji"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Sakrij trenutačnu sesiju."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sakrij"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Postavke"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, provjerite aplik."</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 804587f9bdcd..42e251fb39de 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Javaslatok betöltése…"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Média"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Jelenlegi munkamenet elrejtése."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Elrejtés"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Folytatás"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Beállítások"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktív, ellenőrizze az appot"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 08ef489901ee..e6b71395c42a 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Բեռնման խորհուրդներ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Մեդիա"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Թաքցրեք ընթացիկ աշխատաշրջանը"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Թաքցնել"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Շարունակել"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Կարգավորումներ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Ակտիվ չէ, ստուգեք հավելվածը"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index ba9eca3f0de9..fec4205ba7da 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Memuat rekomendasi"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Menyembunyikan sesi saat ini."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sembunyikan"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Lanjutkan"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Setelan"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nonaktif, periksa aplikasi"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 629581346d46..3a9e63ba9f1a 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Hleður tillögum"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Margmiðlunarefni"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Fela núverandi lotu."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Fela"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Halda áfram"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Stillingar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Óvirkt, athugaðu forrit"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index ef862cb0f919..3eca501b103c 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Caricamento dei consigli"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Contenuti multimediali"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Nascondi la sessione attuale."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Nascondi"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Riprendi"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Impostazioni"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inattivo, controlla l\'app"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 358946d69472..e88c951cf19e 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"בטעינת המלצות"</string>
<string name="controls_media_title" msgid="1746947284862928133">"מדיה"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"הסתרת הסשן הנוכחי."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"הסתרה"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"המשך"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"הגדרות"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"לא פעיל, יש לבדוק את האפליקציה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 9cb872bf1fab..130f682daaf3 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"候補を読み込んでいます"</string>
<string name="controls_media_title" msgid="1746947284862928133">"メディア"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"現在のセッションを非表示にします。"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"非表示"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"再開"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"無効: アプリをご確認ください"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index ef6ff128ed09..d050875c35ce 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"მიმდინარეობს რეკომენდაციების ჩატვირთვა"</string>
<string name="controls_media_title" msgid="1746947284862928133">"მედია"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"დაიმალოს მიმდინარე სესია"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"დამალვა"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"გაგრძელება"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"პარამეტრები"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"არააქტიურია, გადაამოწმეთ აპი"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 08b1f6262f1f..36c726edb791 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Жүктеуге қатысты ұсыныстар"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Мультимедиа"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ағымдағы сеансты жасыру"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Жасыру"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Жалғастыру"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Параметрлер"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Өшірулі. Қолданба тексеріңіз."</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 6d80ee47413c..9d87c583c007 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"កំពុងផ្ទុក​ការណែនាំ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"មេឌៀ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"លាក់វគ្គ​បច្ចុប្បន្ន។"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"លាក់"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"បន្ត"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ការកំណត់"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"អសកម្ម ពិនិត្យមើល​កម្មវិធី"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index db2086458286..901f024c5f71 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ಶಿಫಾರಸುಗಳು ಲೋಡ್ ಆಗುತ್ತಿವೆ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"ಮಾಧ್ಯಮ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ಪ್ರಸ್ತುತ ಸೆಶನ್ ಅನ್ನು ಮರೆಮಾಡಿ."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ಮರೆಮಾಡಿ"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"ಪುನರಾರಂಭಿಸಿ"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ನಿಷ್ಕ್ರಿಯ, ಆ್ಯಪ್ ಪರಿಶೀಲಿಸಿ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index b43eb410c46d..8a6415566676 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"추천 제어 기능 로드 중"</string>
<string name="controls_media_title" msgid="1746947284862928133">"미디어"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"현재 세션을 숨깁니다."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"숨기기"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"다시 시작"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"설정"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"비활성. 앱을 확인하세요."</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 02e468a4f311..3cf41264a4d4 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Сунуштар жүктөлүүдө"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Медиа"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Учурдагы сеансты жашыруу."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Жашыруу"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Улантуу"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Жөндөөлөр"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Жигерсиз. Колдонмону текшериңиз"</string>
diff --git a/packages/SystemUI/res/values-land-television/dimens.xml b/packages/SystemUI/res/values-land-television/dimens.xml
index 499341c662b1..90fc652b05e9 100644
--- a/packages/SystemUI/res/values-land-television/dimens.xml
+++ b/packages/SystemUI/res/values-land-television/dimens.xml
@@ -17,5 +17,8 @@
<resources>
<!-- Width of volume bar -->
<dimen name="volume_dialog_row_width">252dp</dimen>
- <dimen name="volume_dialog_tap_target_size">36dp</dimen>
+ <dimen name="tv_volume_dialog_bubble_size">36dp</dimen>
+ <dimen name="tv_volume_dialog_corner_radius">40dp</dimen>
+ <dimen name="tv_volume_dialog_row_padding">5dp</dimen>
+ <dimen name="tv_volume_number_text_size">16dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 030bdc1ae120..b1c5a5cd887e 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ກຳລັງໂຫຼດຄຳແນະນຳ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"ມີເດຍ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ເຊື່ອງເຊດຊັນປັດຈຸບັນ."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ເຊື່ອງ"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"ສືບຕໍ່"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ການຕັ້ງຄ່າ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ບໍ່ເຮັດວຽກ, ກະລຸນາກວດສອບແອັບ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 6f487416b322..4e9b802f4916 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Įkeliamos rekomendacijos"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Medija"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Slėpti dabartinį seansą."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Slėpti"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Tęsti"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Nustatymai"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktyvu, patikrinkite progr."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index bdea26a1a202..a4c4666fafe3 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -1075,7 +1075,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Notiek ieteikumu ielāde"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multivide"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Paslēpiet pašreizējo sesiju."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Paslēpt"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Atsākt"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Iestatījumi"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktīva, pārbaudiet lietotni"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index c9f3777c6192..7e623ad5032f 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Се вчитуваат препораки"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Аудиовизуелни содржини"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Сокриј ја тековнава сесија."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Сокриј"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Продолжи"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Поставки"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивна, провери апликација"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index c968c2827437..35e642769981 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"നിർദ്ദേശങ്ങൾ ലോഡ് ചെയ്യുന്നു"</string>
<string name="controls_media_title" msgid="1746947284862928133">"മീഡിയ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"നിലവിലെ സെഷൻ മറയ്‌ക്കുക."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"മറയ്‌ക്കുക"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"പുനരാരംഭിക്കുക"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ക്രമീകരണം"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"നിഷ്‌ക്രിയം, ആപ്പ് പരിശോധിക്കൂ"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 9ce6779e9ae4..b4690d418480 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Зөвлөмжүүдийг ачаалж байна"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Медиа"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Одоогийн харилцан үйлдлийг нуугаарай."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Нуух"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Үргэлжлүүлэх"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Тохиргоо"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Идэвхгүй байна, аппыг шалгана уу"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index d7126795089f..4ea965ad80fc 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"शिफारशी लोड करत आहे"</string>
<string name="controls_media_title" msgid="1746947284862928133">"मीडिया"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"सध्याचे सेशन लपवा."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"लपवा"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"पुन्हा सुरू करा"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिंग्ज"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय, ॲप तपासा"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 01e918ade0ee..38ee25c7f3e4 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Memuatkan cadangan"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Sembunyikan sesi semasa."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Sembunyikan"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Sambung semula"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Tetapan"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Tidak aktif, semak apl"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 23b0a06cca8f..150ed94eec38 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"အကြံပြုချက်များ ဖွင့်နေသည်"</string>
<string name="controls_media_title" msgid="1746947284862928133">"မီဒီယာ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"လက်ရှိ စက်ရှင်ကို ဖျောက်ထားမည်။"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ဖျောက်ထားမည်"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"ပယ်ရန်"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"ဆက်လုပ်ရန်"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ဆက်တင်များ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ရပ်နေသည်၊ အက်ပ်ကို စစ်ဆေးပါ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index b0a593fe42f9..d872a89880c9 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Laster inn anbefalinger"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Medier"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Skjul den nåværende økten."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skjul"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Gjenoppta"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Innstillinger"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Sjekk appen"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 09462cf3ffcb..1974e8088971 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -731,11 +731,11 @@
<string name="see_more_title" msgid="7409317011708185729">"थप हेर्नुहोस्"</string>
<string name="appops_camera" msgid="5215967620896725715">"यो अनुप्रयोगले क्यामेराको प्रयोग गर्दै छ।"</string>
<string name="appops_microphone" msgid="8805468338613070149">"यो अनुप्रयोगले माइक्रोफोनको प्रयोग गर्दै छ।"</string>
- <string name="appops_overlay" msgid="4822261562576558490">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य अनुप्रयोगहरूमाथि प्रदर्शन गर्दै छ।"</string>
+ <string name="appops_overlay" msgid="4822261562576558490">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य एपमाथि प्रदर्शन गर्दै छ।"</string>
<string name="appops_camera_mic" msgid="7032239823944420431">"यो अनुप्रयोगले माइक्रोफोन र क्यामेराको प्रयोग गर्दै छ।"</string>
- <string name="appops_camera_overlay" msgid="6466845606058816484">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य अनुप्रयोगहरूमाथि प्रदर्शन गर्नुका साथै क्यामेराको प्रयोग गर्दै छ।"</string>
- <string name="appops_mic_overlay" msgid="4609326508944233061">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य अनुप्रयोगहरूमाथि प्रदर्शन गर्नुका साथै माइक्रोफोनको प्रयोग गर्दै छ।"</string>
- <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य अनुप्रयोगहरूमाथि प्रदर्शन गर्नुका साथै माइक्रोफोन र क्यामेराको प्रयोग गर्दै छ।"</string>
+ <string name="appops_camera_overlay" msgid="6466845606058816484">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य एपमाथि प्रदर्शन गर्नुका साथै क्यामेराको प्रयोग गर्दै छ।"</string>
+ <string name="appops_mic_overlay" msgid="4609326508944233061">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य एपमाथि प्रदर्शन गर्नुका साथै माइक्रोफोनको प्रयोग गर्दै छ।"</string>
+ <string name="appops_camera_mic_overlay" msgid="5584311236445644095">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य एपमाथि प्रदर्शन गर्नुका साथै माइक्रोफोन र क्यामेराको प्रयोग गर्दै छ।"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"सेटिङहरू"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ठिक छ"</string>
<string name="feedback_silenced" msgid="5382212321253328247">"सिस्टमले यो सूचना आउँदा बज्ने ध्वनि बन्द गरेको छ।"</string>
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"सिफारिसहरू लोड गर्दै"</string>
<string name="controls_media_title" msgid="1746947284862928133">"मिडिया"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"हालको सत्र लुकाउनुहोस्।"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"लुकाउनुहोस्"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"सुचारु गर्नुहोस्"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"सेटिङ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय छ, एप जाँच गर्नु…"</string>
@@ -1084,8 +1085,6 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"नयाँ नियन्त्रण सुविधाहरू हेर्न पावर बटन थिचिराख्नुहोस्"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"नियन्त्रण सुविधाहरू थप्नुहोस्"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"नियन्त्रण सुविधाहरू सम्पादन गर्नु…"</string>
- <!-- no translation found for one_handed_tutorial_title (6312198435090726656) -->
- <skip />
- <!-- no translation found for one_handed_tutorial_description (7674850272340517174) -->
- <skip />
+ <string name="one_handed_tutorial_title" msgid="6312198435090726656">"एक हाते मोड प्रयोग गरिँदै छ"</string>
+ <string name="one_handed_tutorial_description" msgid="7674850272340517174">"बाहिर निस्कन, स्क्रिनको पुछारबाट माथितिर स्वाइप गर्नुहोस् वा एपभन्दा माथि जुनसुकै ठाउँमा ट्याप गर्नुहोस्"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 2385017a0df7..9da8afa4d698 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Aanbevelingen laden"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"De huidige sessie verbergen."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Verbergen"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Hervatten"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Instellingen"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactief, check de app"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index d5c077b3ec1b..5b5cbc62fe21 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ସୁପାରିଶଗୁଡ଼ିକ ଲୋଡ୍ କରାଯାଉଛି"</string>
<string name="controls_media_title" msgid="1746947284862928133">"ମିଡିଆ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ବର୍ତ୍ତମାନର ସେସନ୍ ଲୁଚାନ୍ତୁ।"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ଲୁଚାନ୍ତୁ"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"ପୁଣି ଆରମ୍ଭ କରନ୍ତୁ"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ସେଟିଂସ୍"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ନିଷ୍କ୍ରିୟ ଅଛି, ଆପ ଯାଞ୍ଚ କରନ୍ତୁ"</string>
@@ -1084,8 +1085,6 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"ନୂଆ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ଦେଖିବା ପାଇଁ ପାୱାର ବଟନକୁ ଧରି ରଖନ୍ତୁ"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଯୋଗ କରନ୍ତୁ"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ସମ୍ପାଦନ କରନ୍ତୁ"</string>
- <!-- no translation found for one_handed_tutorial_title (6312198435090726656) -->
- <skip />
- <!-- no translation found for one_handed_tutorial_description (7674850272340517174) -->
- <skip />
+ <string name="one_handed_tutorial_title" msgid="6312198435090726656">"ଏକ-ହାତ ମୋଡ୍ ବ୍ୟବହାର କରି"</string>
+ <string name="one_handed_tutorial_description" msgid="7674850272340517174">"ବାହାରି ଯିବା ପାଇଁ, ତଳୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ କିମ୍ବା ଆପ୍ ଆଇକନର ଉପରେ ଯେ କୌଣସି ସ୍ଥାନରେ ଟାପ୍ କରନ୍ତୁ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 11567821397a..5c31ce71ef98 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ਸਿਫ਼ਾਰਸ਼ਾਂ ਲੋਡ ਹੋ ਰਹੀਆਂ ਹਨ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"ਮੀਡੀਆ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ਮੌਜੂਦਾ ਸੈਸ਼ਨ ਨੂੰ ਲੁਕਾਓ।"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ਲੁਕਾਓ"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"ਮੁੜ-ਚਾਲੂ ਕਰੋ"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ਸੈਟਿੰਗਾਂ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ਅਕਿਰਿਆਸ਼ੀਲ, ਐਪ ਦੀ ਜਾਂਚ ਕਰੋ"</string>
@@ -1084,8 +1085,6 @@
<string name="controls_added_tooltip" msgid="4842812921719153085">"ਨਵੇਂ ਕੰਟਰੋਲ ਦੇਖਣ ਲਈ ਪਾਵਰ ਬਟਨ ਦਬਾਈ ਰੱਖੋ"</string>
<string name="controls_menu_add" msgid="4447246119229920050">"ਕੰਟਰੋਲ ਸ਼ਾਮਲ ਕਰੋ"</string>
<string name="controls_menu_edit" msgid="890623986951347062">"ਕੰਟਰੋਲਾਂ ਦਾ ਸੰਪਾਦਨ ਕਰੋ"</string>
- <!-- no translation found for one_handed_tutorial_title (6312198435090726656) -->
- <skip />
- <!-- no translation found for one_handed_tutorial_description (7674850272340517174) -->
- <skip />
+ <string name="one_handed_tutorial_title" msgid="6312198435090726656">"ਇੱਕ ਹੱਥ ਮੋਡ ਵਰਤਣਾ"</string>
+ <string name="one_handed_tutorial_description" msgid="7674850272340517174">"ਬਾਹਰ ਜਾਣ ਲਈ, ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ ਜਾਂ ਐਪ \'ਤੇ ਕਿਤੇ ਵੀ ਟੈਪ ਕਰੋ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 1f6effe431e7..b7ee75057626 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Wczytuję rekomendacje"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimedia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ukryj bieżącą sesję."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ukryj"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Wznów"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ustawienia"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nieaktywny, sprawdź aplikację"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 14d7a84dab28..715b0e45faeb 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregando recomendações"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Mídia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ocultar a sessão atual."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dispensar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configurações"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index a6f7f004f411..1a59de496c91 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"A carregar recomendações…"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Multimédia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Oculte a sessão atual."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Ignorar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Definições"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativa. Consulte a app."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 14d7a84dab28..715b0e45faeb 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregando recomendações"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Mídia"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ocultar a sessão atual."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ocultar"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Dispensar"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Configurações"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 0f15cfcd23f6..49c3ba0c2cd8 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -1075,7 +1075,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Se încarcă recomandările"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ascunde sesiunea actuală."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ascunde"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Reia"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Setări"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactiv, verificați aplicația"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 6196f88a7bfb..7fb456d5f425 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Загрузка рекомендаций…"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Медиа"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Скрыть текущий сеанс?"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Скрыть"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Возобновить"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Настройки"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Нет ответа. Проверьте приложение."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 8aca9f4e0dbd..1cd1ceb21c97 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"නිර්දේශ පූරණය කරමින්"</string>
<string name="controls_media_title" msgid="1746947284862928133">"මාධ්‍ය"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"වත්මන් සැසිය සඟවන්න."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"සඟවන්න"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"ඉවත ලන්න"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"නැවත පටන් ගන්න"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"සැකසීම්"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"අක්‍රියයි, යෙදුම පරීක්ෂා කරන්න"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 45ee562b374c..9d7e7d1cd27c 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Načítavajú sa odporúčania"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Médiá"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Skryť aktuálnu reláciu."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skryť"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Pokračovať"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavenia"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktívne, preverte aplikáciu"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index c7ad8ab92da3..ecbf1d905e5b 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Nalaganje priporočil"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Predstavnost"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Skrije trenutno sejo."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Skrij"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Nadaljuj"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Nastavitve"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, poglejte aplikacijo"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 3e0aecc16d4e..70245b875726 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Po ngarkon rekomandimet"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Fshih sesionin aktual."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Fshih"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Vazhdo"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Cilësimet"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Joaktive, kontrollo aplikacionin"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 985041b3b24d..1d02ca6ab455 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -1075,7 +1075,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Учитавају се препоруке"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Медији"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Сакријте актуелну сесију."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Сакриј"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Настави"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Подешавања"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно. Видите апликацију"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 2018a383b5ed..7a7448be16c5 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Rekommendationer läses in"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Dölj den aktuella sessionen."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Dölj"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Återuppta"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Inställningar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv, kolla appen"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 6eecc0e402fa..b8d95fcd0c1a 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Inapakia mapendekezo"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Maudhui"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ficha kipindi cha sasa."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ficha"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Endelea"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Mipangilio"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Haitumiki, angalia programu"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index a05e0e735620..60c1cf9dcac0 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"பரிந்துரைகளை ஏற்றுகிறது"</string>
<string name="controls_media_title" msgid="1746947284862928133">"மீடியா"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"இந்த அமர்வை மறையுங்கள்."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"மறை"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"தொடர்க"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"அமைப்புகள்"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"செயலில் இல்லை , சரிபார்க்கவும்"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 7d76abd0f20f..6cfe03d95023 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"సిఫార్సులు లోడ్ అవుతున్నాయి"</string>
<string name="controls_media_title" msgid="1746947284862928133">"మీడియా"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ప్రస్తుత సెషన్‌ను దాచు."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"దాచు"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"కొనసాగించండి"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"సెట్టింగ్‌లు"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ఇన్‌యాక్టివ్, యాప్ చెక్ చేయండి"</string>
diff --git a/packages/SystemUI/res/values-television/config.xml b/packages/SystemUI/res/values-television/config.xml
index 1696aab66148..7b1479acc35e 100644
--- a/packages/SystemUI/res/values-television/config.xml
+++ b/packages/SystemUI/res/values-television/config.xml
@@ -43,4 +43,7 @@
<item>com.android.systemui.toast.ToastUI</item>
<item>com.android.systemui.onehanded.OneHandedUI</item>
</string-array>
+
+ <!-- Show a separate icon for low and high volume on the volume dialog -->
+ <bool name="config_showLowMediaVolumeIcon">true</bool>
</resources>
diff --git a/packages/SystemUI/res/values-television/styles.xml b/packages/SystemUI/res/values-television/styles.xml
index b01c5d88e3b3..4cf7034a29bf 100644
--- a/packages/SystemUI/res/values-television/styles.xml
+++ b/packages/SystemUI/res/values-television/styles.xml
@@ -22,4 +22,8 @@
<item name="android:windowEnterAnimation">@null</item>
<item name="android:windowExitAnimation">@null</item>
</style>
+
+ <style name="volume_dialog_theme" parent="qs_theme">
+ <item name="android:colorAccent">@color/tv_volume_dialog_accent</item>
+ </style>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 765c22424e89..a2c1127df5ca 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"กำลังโหลดคำแนะนำ"</string>
<string name="controls_media_title" msgid="1746947284862928133">"สื่อ"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"ซ่อนเซสชันปัจจุบัน"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"ซ่อน"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"เล่นต่อ"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"การตั้งค่า"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ไม่มีการใช้งาน โปรดตรวจสอบแอป"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index c2cae9024a60..e5f0532b0e7b 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Nilo-load ang rekomendasyon"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Itago ang kasalukuyang session."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Itago"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Ituloy"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Mga Setting"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Hindi aktibo, tingnan ang app"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 74b44f2079c6..4943e2d03920 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Öneriler yükleniyor"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Medya"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Mevcut oturumu gizle."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Gizle"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Devam ettir"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Ayarlar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Devre dışı, uygulamaya bakın"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 38c331ade344..447912e08835 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -1081,7 +1081,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Завантаження рекомендацій"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Медіа"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Приховати поточний сеанс."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Приховати"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Відновити"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Налаштування"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, перейдіть у додаток"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 69ddabbe94ac..20b551882344 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"تجاویز لوڈ ہو رہی ہیں"</string>
<string name="controls_media_title" msgid="1746947284862928133">"میڈیا"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"موجودہ سیشن چھپائیں۔"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"چھپائیں"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"دوبارہ شروع کریں"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"ترتیبات"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"غیر فعال، ایپ چیک کریں"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index ed704b0f5597..cf1da7508052 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -227,7 +227,7 @@
<string name="data_connection_roaming" msgid="375650836665414797">"Rouming"</string>
<string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
- <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM karta solinmagan."</string>
+ <string name="accessibility_no_sim" msgid="1140839832913084973">"SIM kartasiz."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobil internet"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobil internet yoniq"</string>
<string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobil internet yoqilmagan"</string>
@@ -1069,7 +1069,7 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Tavsiyalar yuklanmoqda"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Media"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Joriy seans berkitilsin."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Berkitish"</string>
+ <string name="controls_media_dismiss_button" msgid="9081375542265132213">"Yopish"</string>
<string name="controls_media_resume" msgid="1933520684481586053">"Davom etish"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Sozlamalar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nofaol. Ilovani tekshiring"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 5cc209941771..a12a08d0a1e6 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Đang tải các đề xuất"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Nội dung nghe nhìn"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Ẩn phiên hiện tại."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Ẩn"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Tiếp tục"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Cài đặt"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Không hoạt động, hãy kiểm tra ứng dụng"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index f670bf682b64..3382365b7ccb 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在加载推荐内容"</string>
<string name="controls_media_title" msgid="1746947284862928133">"媒体"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"隐藏当前会话。"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"隐藏"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"继续播放"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"设置"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"无效,请检查应用"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 2e26d6153a8f..1d55ca22a43f 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在載入建議"</string>
<string name="controls_media_title" msgid="1746947284862928133">"媒體"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"隱藏目前的工作階段。"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"隱藏"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"繼續播放"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"已停用,請檢查應用程式"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 0049d2ec1f56..e62c164684b3 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在載入建議控制項"</string>
<string name="controls_media_title" msgid="1746947284862928133">"媒體"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"隱藏目前的工作階段。"</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"隱藏"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"繼續播放"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"設定"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"無效,請查看應用程式"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index c8c99b1c18c1..bd7391203dd8 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -1069,7 +1069,8 @@
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Ilayisha izincomo"</string>
<string name="controls_media_title" msgid="1746947284862928133">"Imidiya"</string>
<string name="controls_media_close_session" msgid="3957093425905475065">"Fihla iseshini yamanje."</string>
- <string name="controls_media_dismiss_button" msgid="4485675693008031646">"Fihla"</string>
+ <!-- no translation found for controls_media_dismiss_button (9081375542265132213) -->
+ <skip />
<string name="controls_media_resume" msgid="1933520684481586053">"Qalisa kabusha"</string>
<string name="controls_media_settings_button" msgid="5815790345117172504">"Izilungiselelo"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Akusebenzi, hlola uhlelo lokusebenza"</string>
diff --git a/packages/SystemUI/res/values/colors_tv.xml b/packages/SystemUI/res/values/colors_tv.xml
index 53cd9716c98e..cb49918e4e3f 100644
--- a/packages/SystemUI/res/values/colors_tv.xml
+++ b/packages/SystemUI/res/values/colors_tv.xml
@@ -24,7 +24,11 @@
<!-- Background color for audio recording indicator (G800) -->
<color name="tv_audio_recording_indicator_background">#FF3C4043</color>
- <color name="tv_audio_recording_indicator_pulse">#4DFFFFFF</color>
+ <color name="tv_audio_recording_indicator_icon_background">#CC000000</color>
+ <color name="tv_audio_recording_indicator_stroke">#33FFFFFF</color>
<color name="red">#FFCC0000</color>
+ <color name="tv_volume_dialog_background">#E61F232B</color>
+ <color name="tv_volume_dialog_circle">#08FFFFFF</color>
+ <color name="tv_volume_dialog_accent">#FFDADCE0</color>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index fba43a628387..ce1ca5ad1723 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -565,13 +565,9 @@
<!-- If the config font scale is >= this value, potentially adjust the number of columns-->
<item name="controls_max_columns_adjust_above_font_scale" translatable="false" format="float" type="dimen">1.25</item>
- <!-- One handed mode default offset % of display size -->
- <fraction name="config_one_handed_offset">50%</fraction>
-
<!-- Allow one handed to enable round corner -->
<bool name="config_one_handed_enable_round_corner">true</bool>
- <!-- Animation duration for translating of one handed when trigger / dismiss. -->
- <integer name="config_one_handed_translate_animation_duration">150</integer>
-
+ <!-- Show a separate icon for low and high volume on the volume dialog -->
+ <bool name="config_showLowMediaVolumeIcon">false</bool>
</resources>
diff --git a/packages/SystemUI/res/values/donottranslate.xml b/packages/SystemUI/res/values/donottranslate.xml
index a1c52e55082a..f05be066d2e2 100644
--- a/packages/SystemUI/res/values/donottranslate.xml
+++ b/packages/SystemUI/res/values/donottranslate.xml
@@ -21,5 +21,5 @@
<string name="system_ui_date_pattern" translatable="false">@*android:string/system_ui_date_pattern</string>
<!-- Date format for the always on display. -->
- <item type="string" name="system_ui_aod_date_pattern" translatable="false">@*android:string/system_ui_date_pattern</item>
+ <item type="string" name="system_ui_aod_date_pattern" translatable="false">EEEMMMd</item>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 9e5b94ee855c..ee07e613a0c5 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -387,6 +387,9 @@
<item name="android:homeAsUpIndicator">@drawable/ic_arrow_back</item>
</style>
+ <!-- Overridden by values-television/styles.xml with tv-specific settings -->
+ <style name="volume_dialog_theme" parent="qs_theme"/>
+
<style name="systemui_theme_remote_input" parent="@android:style/Theme.DeviceDefault.Light">
<item name="android:colorAccent">@color/remote_input_accent</item>
</style>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ContextUtils.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ContextUtils.java
new file mode 100644
index 000000000000..1de740a083c2
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ContextUtils.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 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.shared.system;
+
+import android.annotation.UserIdInt;
+import android.content.Context;
+
+public class ContextUtils {
+
+ /** Get the user associated with this context */
+ public static @UserIdInt int getUserId(Context context) {
+ return context.getUserId();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 1db2e32b8cdb..5f00a591860e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -256,7 +256,7 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
mUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y);
mInjectionInflationController = new InjectionInflationController(
- SystemUIFactory.getInstance().getRootComponent());
+ SystemUIFactory.getInstance().getRootComponent().createViewInstanceCreatorFactory());
mViewConfiguration = ViewConfiguration.get(context);
mKeyguardStateController = Dependency.get(KeyguardStateController.class);
mSecondaryLockScreenController = new AdminSecondaryLockScreenController(context, this,
diff --git a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
index 449ed8c3bcdb..2365f128532e 100644
--- a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java
@@ -16,6 +16,7 @@ package com.android.systemui;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+import android.annotation.Nullable;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.slice.SliceManager;
@@ -29,6 +30,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Bundle;
import android.text.BidiFormatter;
+import android.util.EventLog;
import android.util.Log;
import android.widget.CheckBox;
import android.widget.TextView;
@@ -50,10 +52,17 @@ public class SlicePermissionActivity extends Activity implements OnClickListener
mUri = getIntent().getParcelableExtra(SliceProvider.EXTRA_BIND_URI);
mCallingPkg = getIntent().getStringExtra(SliceProvider.EXTRA_PKG);
- mProviderPkg = getIntent().getStringExtra(SliceProvider.EXTRA_PROVIDER_PKG);
+ if (mUri == null) {
+ Log.e(TAG, SliceProvider.EXTRA_BIND_URI + " wasn't provided");
+ finish();
+ return;
+ }
try {
PackageManager pm = getPackageManager();
+ mProviderPkg = pm.resolveContentProvider(mUri.getAuthority(),
+ PackageManager.GET_META_DATA).applicationInfo.packageName;
+ verifyCallingPkg();
CharSequence app1 = BidiFormatter.getInstance().unicodeWrap(pm.getApplicationInfo(
mCallingPkg, 0).loadSafeLabel(pm, PackageItemInfo.DEFAULT_MAX_LABEL_SIZE_PX,
PackageItemInfo.SAFE_LABEL_FLAG_TRIM
@@ -97,4 +106,29 @@ public class SlicePermissionActivity extends Activity implements OnClickListener
public void onDismiss(DialogInterface dialog) {
finish();
}
+
+ private void verifyCallingPkg() {
+ final String providerPkg = getIntent().getStringExtra("provider_pkg");
+ if (providerPkg == null || mProviderPkg.equals(providerPkg)) return;
+ final String callingPkg = getCallingPkg();
+ EventLog.writeEvent(0x534e4554, "159145361", getUid(callingPkg), String.format(
+ "pkg %s (disguised as %s) attempted to request permission to show %s slices in %s",
+ callingPkg, providerPkg, mProviderPkg, mCallingPkg));
+ }
+
+ @Nullable
+ private String getCallingPkg() {
+ final Uri referrer = getReferrer();
+ if (referrer == null) return null;
+ return referrer.getHost();
+ }
+
+ private int getUid(@Nullable final String pkg) {
+ if (pkg == null) return -1;
+ try {
+ return getPackageManager().getApplicationInfo(pkg, 0).uid;
+ } catch (NameNotFoundException e) {
+ }
+ return -1;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
index cacbf969e562..627f5592e667 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
@@ -29,6 +29,10 @@ import androidx.annotation.Nullable;
import androidx.core.app.AppComponentFactory;
import com.android.systemui.dagger.ContextComponentHelper;
+import com.android.systemui.dagger.GlobalRootComponent;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import javax.inject.Inject;
@@ -81,8 +85,17 @@ public class SystemUIAppComponentFactory extends AppComponentFactory {
((ContextInitializer) contentProvider).setContextAvailableCallback(
context -> {
SystemUIFactory.createFromConfig(context);
- SystemUIFactory.getInstance().getRootComponent().inject(
- contentProvider);
+ GlobalRootComponent rootComponent =
+ SystemUIFactory.getInstance().getRootComponent();
+ try {
+ Method injectMethod = rootComponent.getClass()
+ .getMethod("inject", contentProvider.getClass());
+ injectMethod.invoke(rootComponent, contentProvider);
+ } catch (NoSuchMethodException
+ | IllegalAccessException
+ | InvocationTargetException e) {
+ // no-op
+ }
}
);
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index c84701c9512e..4f78f65f0121 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -32,7 +32,7 @@ import android.util.Log;
import android.util.TimingsTraceLog;
import com.android.systemui.dagger.ContextComponentHelper;
-import com.android.systemui.dagger.SystemUIRootComponent;
+import com.android.systemui.dagger.GlobalRootComponent;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.util.NotificationChannels;
@@ -57,7 +57,7 @@ public class SystemUIApplication extends Application implements
private SystemUI[] mServices;
private boolean mServicesStarted;
private SystemUIAppComponentFactory.ContextAvailableCallback mContextAvailableCallback;
- private SystemUIRootComponent mRootComponent;
+ private GlobalRootComponent mRootComponent;
public SystemUIApplication() {
super();
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 1a15c0aae8c1..d987ad3b218d 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -28,8 +28,10 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.bubbles.BubbleController;
-import com.android.systemui.dagger.DaggerSystemUIRootComponent;
-import com.android.systemui.dagger.SystemUIRootComponent;
+import com.android.systemui.dagger.DaggerGlobalRootComponent;
+import com.android.systemui.dagger.GlobalRootComponent;
+import com.android.systemui.dagger.SysUIComponent;
+import com.android.systemui.dagger.WMComponent;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -53,7 +55,9 @@ public class SystemUIFactory {
private static final String TAG = "SystemUIFactory";
static SystemUIFactory mFactory;
- private SystemUIRootComponent mRootComponent;
+ private GlobalRootComponent mRootComponent;
+ private WMComponent mWMComponent;
+ private SysUIComponent mSysUIComponent;
public static <T extends SystemUIFactory> T getInstance() {
return (T) mFactory;
@@ -88,7 +92,10 @@ public class SystemUIFactory {
public SystemUIFactory() {}
private void init(Context context) {
- mRootComponent = buildSystemUIRootComponent(context);
+ mRootComponent = buildGlobalRootComponent(context);
+ mWMComponent = mRootComponent.getWMComponentBuilder().build();
+ // TODO: use WMComponent to pass APIs into the SysUIComponent.
+ mSysUIComponent = mRootComponent.getSysUIComponent().build();
// Every other part of our codebase currently relies on Dependency, so we
// really need to ensure the Dependency gets initialized early on.
@@ -96,13 +103,13 @@ public class SystemUIFactory {
dependency.start();
}
- protected SystemUIRootComponent buildSystemUIRootComponent(Context context) {
- return DaggerSystemUIRootComponent.builder()
+ protected GlobalRootComponent buildGlobalRootComponent(Context context) {
+ return DaggerGlobalRootComponent.builder()
.context(context)
.build();
}
- public SystemUIRootComponent getRootComponent() {
+ public GlobalRootComponent getRootComponent() {
return mRootComponent;
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
index 816bcf8f274b..d5f74a86fd94 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
@@ -53,8 +53,8 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall
ActivityInfo.CONFIG_DENSITY | ActivityInfo.CONFIG_ORIENTATION;
@VisibleForTesting
- protected WindowMagnificationController mWindowMagnificationController;
- protected final ModeSwitchesController mModeSwitchesController;
+ protected WindowMagnificationAnimationController mWindowMagnificationAnimationController;
+ private final ModeSwitchesController mModeSwitchesController;
private final Handler mHandler;
private final AccessibilityManager mAccessibilityManager;
private final CommandQueue mCommandQueue;
@@ -72,6 +72,11 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall
Context.ACCESSIBILITY_SERVICE);
mCommandQueue = commandQueue;
mModeSwitchesController = modeSwitchesController;
+ final WindowMagnificationController controller = new WindowMagnificationController(mContext,
+ mHandler, new SfVsyncFrameCallbackProvider(), null,
+ new SurfaceControl.Transaction(), this);
+ mWindowMagnificationAnimationController = new WindowMagnificationAnimationController(
+ mContext, controller);
}
@Override
@@ -81,9 +86,7 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall
return;
}
mLastConfiguration.setTo(newConfig);
- if (mWindowMagnificationController != null) {
- mWindowMagnificationController.onConfigurationChanged(configDiff);
- }
+ mWindowMagnificationAnimationController.onConfigurationChanged(configDiff);
if (mModeSwitchesController != null) {
mModeSwitchesController.onConfigurationChanged(configDiff);
}
@@ -97,39 +100,25 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall
@MainThread
void enableWindowMagnification(int displayId, float scale, float centerX, float centerY) {
//TODO: b/144080869 support multi-display.
- if (mWindowMagnificationController == null) {
- mWindowMagnificationController = new WindowMagnificationController(mContext,
- mHandler,
- new SfVsyncFrameCallbackProvider(),
- null, new SurfaceControl.Transaction(),
- this);
- }
- mWindowMagnificationController.enableWindowMagnification(scale, centerX, centerY);
+ mWindowMagnificationAnimationController.enableWindowMagnification(scale, centerX, centerY);
}
@MainThread
void setScale(int displayId, float scale) {
//TODO: b/144080869 support multi-display.
- if (mWindowMagnificationController != null) {
- mWindowMagnificationController.setScale(scale);
- }
+ mWindowMagnificationAnimationController.setScale(scale);
}
@MainThread
void moveWindowMagnifier(int displayId, float offsetX, float offsetY) {
//TODO: b/144080869 support multi-display.
- if (mWindowMagnificationController != null) {
- mWindowMagnificationController.moveWindowMagnifier(offsetX, offsetY);
- }
+ mWindowMagnificationAnimationController.moveWindowMagnifier(offsetX, offsetY);
}
@MainThread
void disableWindowMagnification(int displayId) {
//TODO: b/144080869 support multi-display.
- if (mWindowMagnificationController != null) {
- mWindowMagnificationController.deleteWindowMagnification();
- }
- mWindowMagnificationController = null;
+ mWindowMagnificationAnimationController.deleteWindowMagnification();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java
new file mode 100644
index 000000000000..ae51623f3dc2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2020 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.accessibility;
+
+import android.animation.Animator;
+import android.animation.ValueAnimator;
+import android.annotation.IntDef;
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+import android.view.animation.AccelerateInterpolator;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.R;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Provides same functionality of {@link WindowMagnificationController}. Some methods run with
+ * the animation.
+ */
+class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUpdateListener,
+ Animator.AnimatorListener {
+
+ private static final String TAG = "WindowMagnificationBridge";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({STATE_DISABLED, STATE_ENABLED, STATE_DISABLING, STATE_ENABLING})
+ @interface MagnificationState {}
+
+ //The window magnification is disabled.
+ private static final int STATE_DISABLED = 0;
+ //The window magnification is enabled.
+ private static final int STATE_ENABLED = 1;
+ //The window magnification is going to be disabled when the animation is end.
+ private static final int STATE_DISABLING = 2;
+ //The animation is running for enabling the window magnification.
+ private static final int STATE_ENABLING = 3;
+
+ private final WindowMagnificationController mController;
+ private final ValueAnimator mValueAnimator;
+ private final AnimationSpec mStartSpec = new AnimationSpec();
+ private final AnimationSpec mEndSpec = new AnimationSpec();
+ private final Context mContext;
+
+ @MagnificationState
+ private int mState = STATE_DISABLED;
+
+ WindowMagnificationAnimationController(
+ Context context, WindowMagnificationController controller) {
+ this(context, controller, newValueAnimator(context.getResources()));
+ }
+
+ @VisibleForTesting
+ WindowMagnificationAnimationController(Context context,
+ WindowMagnificationController controller, ValueAnimator valueAnimator) {
+ mContext = context;
+ mController = controller;
+ mValueAnimator = valueAnimator;
+ mValueAnimator.addUpdateListener(this);
+ mValueAnimator.addListener(this);
+ }
+
+ /**
+ * Wraps {@link WindowMagnificationController#enableWindowMagnification(float, float, float)}
+ * with transition animation. If the window magnification is not enabled, the scale will start
+ * from 1.0 and the center won't be changed during the animation. If {@link #mState} is
+ * {@code STATE_DISABLING}, the animation runs in reverse.
+ *
+ * @param scale the target scale, or {@link Float#NaN} to leave unchanged.
+ * @param centerX the screen-relative X coordinate around which to center,
+ * or {@link Float#NaN} to leave unchanged.
+ * @param centerY the screen-relative Y coordinate around which to center,
+ * or {@link Float#NaN} to leave unchanged.
+ *
+ * @see #onAnimationUpdate(ValueAnimator)
+ */
+ void enableWindowMagnification(float scale, float centerX, float centerY) {
+ if (mState == STATE_ENABLING) {
+ mValueAnimator.cancel();
+ }
+ setupEnableAnimationSpecs(scale, centerX, centerY);
+
+ if (mEndSpec.equals(mStartSpec)) {
+ setState(STATE_ENABLED);
+ } else {
+ if (mState == STATE_DISABLING) {
+ mValueAnimator.reverse();
+ } else {
+ mValueAnimator.start();
+ }
+ setState(STATE_ENABLING);
+ }
+ }
+
+ private void setupEnableAnimationSpecs(float scale, float centerX, float centerY) {
+ final float currentScale = mController.getScale();
+ final float currentCenterX = mController.getCenterX();
+ final float currentCenterY = mController.getCenterY();
+
+ if (mState == STATE_DISABLED) {
+ //We don't need to offset the center during the animation.
+ mStartSpec.set(/* scale*/ 1.0f, centerX, centerY);
+ mEndSpec.set(Float.isNaN(scale) ? mContext.getResources().getInteger(
+ R.integer.magnification_default_scale) : scale, centerX, centerY);
+ } else {
+ mStartSpec.set(currentScale, currentCenterX, currentCenterY);
+ mEndSpec.set(Float.isNaN(scale) ? currentScale : scale,
+ Float.isNaN(centerX) ? currentCenterX : centerX,
+ Float.isNaN(centerY) ? currentCenterY : centerY);
+ }
+ if (DEBUG) {
+ Log.d(TAG, "SetupEnableAnimationSpecs : mStartSpec = " + mStartSpec + ", endSpec = "
+ + mEndSpec);
+ }
+ }
+
+ /**
+ * Wraps {@link WindowMagnificationController#setScale(float)}. If the animation is
+ * running, it has no effect.
+ */
+ void setScale(float scale) {
+ if (mValueAnimator.isRunning()) {
+ return;
+ }
+ mController.setScale(scale);
+ }
+
+ /**
+ * Wraps {@link WindowMagnificationController#deleteWindowMagnification()}} with transition
+ * animation. If the window magnification is enabling, it runs the animation in reverse.
+ */
+ void deleteWindowMagnification() {
+ if (mState == STATE_DISABLED || mState == STATE_DISABLING) {
+ return;
+ }
+ mStartSpec.set(/* scale*/ 1.0f, Float.NaN, Float.NaN);
+ mEndSpec.set(/* scale*/ mController.getScale(), Float.NaN, Float.NaN);
+
+ mValueAnimator.reverse();
+ setState(STATE_DISABLING);
+ }
+
+ /**
+ * Wraps {@link WindowMagnificationController#moveWindowMagnifier(float, float)}. If the
+ * animation is running, it has no effect.
+ * @param offsetX the amount in pixels to offset the window magnifier in the X direction, in
+ * current screen pixels.
+ * @param offsetY the amount in pixels to offset the window magnifier in the Y direction, in
+ * current screen pixels.
+ */
+ void moveWindowMagnifier(float offsetX, float offsetY) {
+ if (mValueAnimator.isRunning()) {
+ return;
+ }
+ mController.moveWindowMagnifier(offsetX, offsetY);
+ }
+
+ void onConfigurationChanged(int configDiff) {
+ mController.onConfigurationChanged(configDiff);
+ }
+
+ private void setState(@MagnificationState int state) {
+ if (DEBUG) {
+ Log.d(TAG, "setState from " + mState + " to " + state);
+ }
+ mState = state;
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mState == STATE_DISABLING) {
+ mController.deleteWindowMagnification();
+ setState(STATE_DISABLED);
+ } else if (mState == STATE_ENABLING) {
+ setState(STATE_ENABLED);
+ } else {
+ Log.w(TAG, "onAnimationEnd unexpected state:" + mState);
+ }
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+ }
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ final float fract = animation.getAnimatedFraction();
+ final float sentScale = mStartSpec.mScale + (mEndSpec.mScale - mStartSpec.mScale) * fract;
+ final float centerX =
+ mStartSpec.mCenterX + (mEndSpec.mCenterX - mStartSpec.mCenterX) * fract;
+ final float centerY =
+ mStartSpec.mCenterY + (mEndSpec.mCenterY - mStartSpec.mCenterY) * fract;
+ mController.enableWindowMagnification(sentScale, centerX, centerY);
+ }
+
+ private static ValueAnimator newValueAnimator(Resources resources) {
+ final ValueAnimator valueAnimator = new ValueAnimator();
+ valueAnimator.setDuration(
+ resources.getInteger(com.android.internal.R.integer.config_longAnimTime));
+ valueAnimator.setInterpolator(new AccelerateInterpolator(2.5f));
+ valueAnimator.setFloatValues(0.0f, 1.0f);
+ return valueAnimator;
+ }
+
+ private static class AnimationSpec {
+ private float mScale = Float.NaN;
+ private float mCenterX = Float.NaN;
+ private float mCenterY = Float.NaN;
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other == null || getClass() != other.getClass()) {
+ return false;
+ }
+
+ final AnimationSpec s = (AnimationSpec) other;
+ return mScale == s.mScale && mCenterX == s.mCenterX && mCenterY == s.mCenterY;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = (mScale != +0.0f ? Float.floatToIntBits(mScale) : 0);
+ result = 31 * result + (mCenterX != +0.0f ? Float.floatToIntBits(mCenterX) : 0);
+ result = 31 * result + (mCenterY != +0.0f ? Float.floatToIntBits(mCenterY) : 0);
+ return result;
+ }
+
+ void set(float scale, float centerX, float centerY) {
+ mScale = scale;
+ mCenterX = centerX;
+ mCenterY = centerY;
+ }
+
+ @Override
+ public String toString() {
+ return "AnimationSpec{"
+ + "mScale=" + mScale
+ + ", mCenterX=" + mCenterX
+ + ", mCenterY=" + mCenterY
+ + '}';
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index 798b751c03ee..494a0f64cea4 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -150,7 +150,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
mMirrorViewGeometryVsyncCallback =
l -> {
- if (mMirrorView != null && mMirrorSurface != null) {
+ if (isWindowVisible() && mMirrorSurface != null) {
calculateSourceBounds(mMagnificationFrame, mScale);
// The final destination for the magnification surface should be at 0,0
// since the ViewRootImpl's position will change
@@ -203,13 +203,13 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
* @param configDiff a bit mask of the differences between the configurations
*/
void onConfigurationChanged(int configDiff) {
+ if (!isWindowVisible()) {
+ return;
+ }
if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0) {
updateDimensions();
- // TODO(b/145780606): update toggle button UI.
- if (mMirrorView != null) {
- mWm.removeView(mMirrorView);
- createMirrorWindow();
- }
+ mWm.removeView(mMirrorView);
+ createMirrorWindow();
} else if ((configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
onRotate();
}
@@ -502,7 +502,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
/**
* Enables window magnification with specified parameters.
*
- * @param scale the target scale
+ * @param scale the target scale, or {@link Float#NaN} to leave unchanged
* @param centerX the screen-relative X coordinate around which to center,
* or {@link Float#NaN} to leave unchanged.
* @param centerY the screen-relative Y coordinate around which to center,
@@ -513,10 +513,10 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
: centerX - mMagnificationFrame.exactCenterX();
final float offsetY = Float.isNaN(centerY) ? 0
: centerY - mMagnificationFrame.exactCenterY();
- mScale = scale;
+ mScale = Float.isNaN(scale) ? mScale : scale;
setMagnificationFrameBoundary();
updateMagnificationFramePosition((int) offsetX, (int) offsetY);
- if (mMirrorView == null) {
+ if (!isWindowVisible()) {
createMirrorWindow();
showControls();
} else {
@@ -527,10 +527,10 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
/**
* Sets the scale of the magnified region if it's visible.
*
- * @param scale the target scale
+ * @param scale the target scale, or {@link Float#NaN} to leave unchanged
*/
void setScale(float scale) {
- if (mMirrorView == null || mScale == scale) {
+ if (!isWindowVisible() || mScale == scale) {
return;
}
enableWindowMagnification(scale, Float.NaN, Float.NaN);
@@ -552,4 +552,35 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
modifyWindowMagnification(mTransaction);
}
}
+
+ /**
+ * Gets the scale.
+ * @return {@link Float#NaN} if the window is invisible.
+ */
+ float getScale() {
+ return isWindowVisible() ? mScale : Float.NaN;
+ }
+
+ /**
+ * Returns the screen-relative X coordinate of the center of the magnified bounds.
+ *
+ * @return the X coordinate. {@link Float#NaN} if the window is invisible.
+ */
+ float getCenterX() {
+ return isWindowVisible() ? mMagnificationFrame.exactCenterX() : Float.NaN;
+ }
+
+ /**
+ * Returns the screen-relative Y coordinate of the center of the magnified bounds.
+ *
+ * @return the Y coordinate. {@link Float#NaN} if the window is invisible.
+ */
+ float getCenterY() {
+ return isWindowVisible() ? mMagnificationFrame.exactCenterY() : Float.NaN;
+ }
+
+ //The window is visible when it is existed.
+ private boolean isWindowVisible() {
+ return mMirrorView != null;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpItem.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpItem.java
index 7e5b42653210..93a8df41c673 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpItem.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpItem.java
@@ -25,7 +25,9 @@ public class AppOpItem {
private int mUid;
private String mPackageName;
private long mTimeStarted;
- private String mState;
+ private StringBuilder mState;
+ // This is only used for items with mCode == AppOpsManager.OP_RECORD_AUDIO
+ private boolean mSilenced;
public AppOpItem(int code, int uid, String packageName, long timeStarted) {
this.mCode = code;
@@ -36,9 +38,8 @@ public class AppOpItem {
.append("AppOpItem(")
.append("Op code=").append(code).append(", ")
.append("UID=").append(uid).append(", ")
- .append("Package name=").append(packageName)
- .append(")")
- .toString();
+ .append("Package name=").append(packageName).append(", ")
+ .append("Paused=");
}
public int getCode() {
@@ -57,8 +58,16 @@ public class AppOpItem {
return mTimeStarted;
}
+ public void setSilenced(boolean silenced) {
+ mSilenced = silenced;
+ }
+
+ public boolean isSilenced() {
+ return mSilenced;
+ }
+
@Override
public String toString() {
- return mState;
+ return mState.append(mSilenced).append(")").toString();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index 6512624f5064..8187a2235c0a 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -19,6 +19,8 @@ package com.android.systemui.appops;
import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.media.AudioManager;
+import android.media.AudioRecordingConfiguration;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
@@ -63,6 +65,7 @@ public class AppOpsControllerImpl implements AppOpsController,
private static final boolean DEBUG = false;
private final AppOpsManager mAppOps;
+ private final AudioManager mAudioManager;
private H mBGHandler;
private final List<AppOpsController.Callback> mCallbacks = new ArrayList<>();
private final SparseArray<Set<Callback>> mCallbacksByCode = new SparseArray<>();
@@ -73,6 +76,9 @@ public class AppOpsControllerImpl implements AppOpsController,
private final List<AppOpItem> mActiveItems = new ArrayList<>();
@GuardedBy("mNotedItems")
private final List<AppOpItem> mNotedItems = new ArrayList<>();
+ @GuardedBy("mActiveItems")
+ private final SparseArray<ArrayList<AudioRecordingConfiguration>> mRecordingsByUid =
+ new SparseArray<>();
protected static final int[] OPS = new int[] {
AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION,
@@ -88,7 +94,8 @@ public class AppOpsControllerImpl implements AppOpsController,
Context context,
@Background Looper bgLooper,
DumpManager dumpManager,
- PermissionFlagsCache cache
+ PermissionFlagsCache cache,
+ AudioManager audioManager
) {
mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
mFlagsCache = cache;
@@ -97,6 +104,7 @@ public class AppOpsControllerImpl implements AppOpsController,
for (int i = 0; i < numOps; i++) {
mCallbacksByCode.put(OPS[i], new ArraySet<>());
}
+ mAudioManager = audioManager;
dumpManager.registerDumpable(TAG, this);
}
@@ -111,12 +119,19 @@ public class AppOpsControllerImpl implements AppOpsController,
if (listening) {
mAppOps.startWatchingActive(OPS, this);
mAppOps.startWatchingNoted(OPS, this);
+ mAudioManager.registerAudioRecordingCallback(mAudioRecordingCallback, mBGHandler);
+ mBGHandler.post(() -> mAudioRecordingCallback.onRecordingConfigChanged(
+ mAudioManager.getActiveRecordingConfigurations()));
+
} else {
mAppOps.stopWatchingActive(this);
mAppOps.stopWatchingNoted(this);
+ mAudioManager.unregisterAudioRecordingCallback(mAudioRecordingCallback);
+
mBGHandler.removeCallbacksAndMessages(null); // null removes all
synchronized (mActiveItems) {
mActiveItems.clear();
+ mRecordingsByUid.clear();
}
synchronized (mNotedItems) {
mNotedItems.clear();
@@ -189,9 +204,12 @@ public class AppOpsControllerImpl implements AppOpsController,
AppOpItem item = getAppOpItemLocked(mActiveItems, code, uid, packageName);
if (item == null && active) {
item = new AppOpItem(code, uid, packageName, System.currentTimeMillis());
+ if (code == AppOpsManager.OP_RECORD_AUDIO) {
+ item.setSilenced(isAnyRecordingPausedLocked(uid));
+ }
mActiveItems.add(item);
if (DEBUG) Log.w(TAG, "Added item: " + item.toString());
- return true;
+ return !item.isSilenced();
} else if (item != null && !active) {
mActiveItems.remove(item);
if (DEBUG) Log.w(TAG, "Removed item: " + item.toString());
@@ -215,7 +233,7 @@ public class AppOpsControllerImpl implements AppOpsController,
active = getAppOpItemLocked(mActiveItems, code, uid, packageName) != null;
}
if (!active) {
- notifySuscribers(code, uid, packageName, false);
+ notifySuscribersWorker(code, uid, packageName, false);
}
}
@@ -324,7 +342,7 @@ public class AppOpsControllerImpl implements AppOpsController,
AppOpItem item = mActiveItems.get(i);
if ((userId == UserHandle.USER_ALL
|| UserHandle.getUserId(item.getUid()) == userId)
- && isUserVisible(item)) {
+ && isUserVisible(item) && !item.isSilenced()) {
list.add(item);
}
}
@@ -343,6 +361,10 @@ public class AppOpsControllerImpl implements AppOpsController,
return list;
}
+ private void notifySuscribers(int code, int uid, String packageName, boolean active) {
+ mBGHandler.post(() -> notifySuscribersWorker(code, uid, packageName, active));
+ }
+
@Override
public void onOpActiveChanged(int code, int uid, String packageName, boolean active) {
if (DEBUG) {
@@ -360,7 +382,7 @@ public class AppOpsControllerImpl implements AppOpsController,
// If active is false, we only send the update if the op is not actively noted (prevent
// early removal)
if (!alsoNoted) {
- mBGHandler.post(() -> notifySuscribers(code, uid, packageName, active));
+ notifySuscribers(code, uid, packageName, active);
}
}
@@ -378,11 +400,11 @@ public class AppOpsControllerImpl implements AppOpsController,
alsoActive = getAppOpItemLocked(mActiveItems, code, uid, packageName) != null;
}
if (!alsoActive) {
- mBGHandler.post(() -> notifySuscribers(code, uid, packageName, true));
+ notifySuscribers(code, uid, packageName, true);
}
}
- private void notifySuscribers(int code, int uid, String packageName, boolean active) {
+ private void notifySuscribersWorker(int code, int uid, String packageName, boolean active) {
if (mCallbacksByCode.contains(code) && isUserVisible(code, uid, packageName)) {
if (DEBUG) Log.d(TAG, "Notifying of change in package " + packageName);
for (Callback cb: mCallbacksByCode.get(code)) {
@@ -408,6 +430,61 @@ public class AppOpsControllerImpl implements AppOpsController,
}
+ private boolean isAnyRecordingPausedLocked(int uid) {
+ List<AudioRecordingConfiguration> configs = mRecordingsByUid.get(uid);
+ if (configs == null) return false;
+ int configsNum = configs.size();
+ for (int i = 0; i < configsNum; i++) {
+ AudioRecordingConfiguration config = configs.get(i);
+ if (config.isClientSilenced()) return true;
+ }
+ return false;
+ }
+
+ private void updateRecordingPausedStatus() {
+ synchronized (mActiveItems) {
+ int size = mActiveItems.size();
+ for (int i = 0; i < size; i++) {
+ AppOpItem item = mActiveItems.get(i);
+ if (item.getCode() == AppOpsManager.OP_RECORD_AUDIO) {
+ boolean paused = isAnyRecordingPausedLocked(item.getUid());
+ if (item.isSilenced() != paused) {
+ item.setSilenced(paused);
+ notifySuscribers(
+ item.getCode(),
+ item.getUid(),
+ item.getPackageName(),
+ !item.isSilenced()
+ );
+ }
+ }
+ }
+ }
+ }
+
+ private AudioManager.AudioRecordingCallback mAudioRecordingCallback =
+ new AudioManager.AudioRecordingCallback() {
+ @Override
+ public void onRecordingConfigChanged(List<AudioRecordingConfiguration> configs) {
+ synchronized (mActiveItems) {
+ mRecordingsByUid.clear();
+ final int recordingsCount = configs.size();
+ for (int i = 0; i < recordingsCount; i++) {
+ AudioRecordingConfiguration recording = configs.get(i);
+
+ ArrayList<AudioRecordingConfiguration> recordings = mRecordingsByUid.get(
+ recording.getClientUid());
+ if (recordings == null) {
+ recordings = new ArrayList<>();
+ mRecordingsByUid.put(recording.getClientUid(), recordings);
+ }
+ recordings.add(recording);
+ }
+ }
+ updateRecordingPausedStatus();
+ }
+ };
+
protected class H extends Handler {
H(Looper looper) {
super(looper);
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt b/packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt
index 8b953fa46441..be089b12a95d 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt
@@ -21,7 +21,7 @@ import com.android.internal.logging.UiEventLogger
enum class AssistantSessionEvent(private val id: Int) : UiEventLogger.UiEventEnum {
@UiEvent(doc = "Unknown assistant session event")
- ASSISTANT_SESSION_UNKNOWN(523),
+ ASSISTANT_SESSION_UNKNOWN(0),
@UiEvent(doc = "Assistant session dismissed due to timeout")
ASSISTANT_SESSION_TIMEOUT_DISMISS(524),
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index c5639ea6fcde..9c5f9fe8bcc0 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -139,7 +139,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
@IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED,
DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION, DISMISS_NO_LONGER_BUBBLE,
DISMISS_USER_CHANGED, DISMISS_GROUP_CANCELLED, DISMISS_INVALID_INTENT,
- DISMISS_OVERFLOW_MAX_REACHED, DISMISS_SHORTCUT_REMOVED, DISMISS_PACKAGE_REMOVED})
+ DISMISS_OVERFLOW_MAX_REACHED, DISMISS_SHORTCUT_REMOVED, DISMISS_PACKAGE_REMOVED,
+ DISMISS_NO_BUBBLE_UP})
@Target({FIELD, LOCAL_VARIABLE, PARAMETER})
@interface DismissReason {}
@@ -156,6 +157,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
static final int DISMISS_OVERFLOW_MAX_REACHED = 11;
static final int DISMISS_SHORTCUT_REMOVED = 12;
static final int DISMISS_PACKAGE_REMOVED = 13;
+ static final int DISMISS_NO_BUBBLE_UP = 14;
private final Context mContext;
private final NotificationEntryManager mNotificationEntryManager;
@@ -1262,8 +1264,18 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
rankingMap.getRanking(key, mTmpRanking);
boolean isActiveBubble = mBubbleData.hasAnyBubbleWithKey(key);
if (isActiveBubble && !mTmpRanking.canBubble()) {
- mBubbleData.dismissBubbleWithKey(entry.getKey(),
- BubbleController.DISMISS_BLOCKED);
+ // If this entry is no longer allowed to bubble, dismiss with the BLOCKED reason.
+ // This means that the app or channel's ability to bubble has been revoked.
+ mBubbleData.dismissBubbleWithKey(
+ key, BubbleController.DISMISS_BLOCKED);
+ } else if (isActiveBubble
+ && !mNotificationInterruptStateProvider.shouldBubbleUp(entry)) {
+ // If this entry is allowed to bubble, but cannot currently bubble up, dismiss it.
+ // This happens when DND is enabled and configured to hide bubbles. Dismissing with
+ // the reason DISMISS_NO_BUBBLE_UP will retain the underlying notification, so that
+ // the bubble will be re-created if shouldBubbleUp returns true.
+ mBubbleData.dismissBubbleWithKey(
+ key, BubbleController.DISMISS_NO_BUBBLE_UP);
} else if (entry != null && mTmpRanking.isBubble() && !isActiveBubble) {
entry.setFlagBubble(true);
onEntryUpdated(entry);
@@ -1340,8 +1352,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
mStackView.removeBubble(bubble);
}
- // If the bubble is removed for user switching, leave the notification in place.
- if (reason == DISMISS_USER_CHANGED) {
+ // Leave the notification in place if we're dismissing due to user switching, or
+ // because DND is suppressing the bubble. In both of those cases, we need to be able
+ // to restore the bubble from the notification later.
+ if (reason == DISMISS_USER_CHANGED || reason == DISMISS_NO_BUBBLE_UP) {
continue;
}
if (reason == DISMISS_NOTIF_CANCEL) {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
index 9fdbb6daca51..9c55095e85e5 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/GlobalRootComponent.java
@@ -16,9 +16,6 @@
package com.android.systemui.dagger;
-import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
-
-import android.content.ContentProvider;
import android.content.Context;
import com.android.systemui.BootCompleteCacheImpl;
@@ -26,14 +23,12 @@ import com.android.systemui.Dependency;
import com.android.systemui.InitController;
import com.android.systemui.SystemUIAppComponentFactory;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.KeyguardSliceProvider;
import com.android.systemui.onehanded.dagger.OneHandedModule;
import com.android.systemui.pip.phone.dagger.PipModule;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.InjectionInflationController;
-import javax.inject.Named;
import javax.inject.Singleton;
import dagger.BindsInstance;
@@ -42,6 +37,7 @@ import dagger.Component;
/**
* Root component for Dagger injection.
*/
+// TODO(b/162923491): Move most of these modules to SysUIComponent.
@Singleton
@Component(modules = {
DefaultComponentBinder.class,
@@ -52,21 +48,32 @@ import dagger.Component;
SystemServicesModule.class,
SystemUIBinder.class,
SystemUIModule.class,
- SystemUIDefaultModule.class})
-public interface SystemUIRootComponent {
+ SystemUIDefaultModule.class,
+ WMModule.class})
+public interface GlobalRootComponent {
/**
- * Builder for a SystemUIRootComponent.
+ * Builder for a GlobalRootComponent.
*/
@Component.Builder
interface Builder {
@BindsInstance
Builder context(Context context);
- SystemUIRootComponent build();
+ GlobalRootComponent build();
}
/**
+ * Builder for a WMComponent.
+ */
+ WMComponent.Builder getWMComponentBuilder();
+
+ /**
+ * Builder for a SysuiComponent.
+ */
+ SysUIComponent.Builder getSysUIComponent();
+
+ /**
* Provides a BootCompleteCache.
*/
@Singleton
@@ -95,28 +102,15 @@ public interface SystemUIRootComponent {
DumpManager createDumpManager();
/**
- * FragmentCreator generates all Fragments that need injection.
- */
- @Singleton
- FragmentService.FragmentCreator createFragmentCreator();
-
-
- /**
* Creates a InitController.
*/
@Singleton
InitController getInitController();
/**
- * ViewCreator generates all Views that need injection.
- */
- InjectionInflationController.ViewCreator createViewCreator();
-
- /**
- * Whether notification long press is allowed.
+ * ViewInstanceCreator generates all Views that need injection.
*/
- @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME)
- boolean allowNotificationLongPressName();
+ InjectionInflationController.ViewInstanceCreator.Factory createViewInstanceCreatorFactory();
/**
* Member injection into the supplied argument.
@@ -126,10 +120,5 @@ public interface SystemUIRootComponent {
/**
* Member injection into the supplied argument.
*/
- void inject(ContentProvider contentProvider);
-
- /**
- * Member injection into the supplied argument.
- */
void inject(KeyguardSliceProvider keyguardSliceProvider);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
new file mode 100644
index 000000000000..9b527bfeda27
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -0,0 +1,35 @@
+/*
+ * 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.dagger;
+
+import dagger.Subcomponent;
+
+/**
+ * Dagger Subcomponent for Core SysUI.
+ */
+@SysUISingleton
+@Subcomponent(modules = {})
+public interface SysUIComponent {
+
+ /**
+ * Builder for a SysUIComponent.
+ */
+ @Subcomponent.Builder
+ interface Builder {
+ SysUIComponent build();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUISingleton.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUISingleton.java
new file mode 100644
index 000000000000..a4b33427cbda
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUISingleton.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 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.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Scope;
+
+/**
+ * Scope annotation for singleton items within the SysUIComponent.
+ */
+@Documented
+@Retention(RUNTIME)
+@Scope
+public @interface SysUISingleton {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index 803e56db8ff3..4fd31c7609e2 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -72,7 +72,14 @@ import dagger.Provides;
* A dagger module for injecting default implementations of components of System UI that may be
* overridden by the System UI implementation.
*/
-@Module(includes = {DividerModule.class, QSModule.class, WindowManagerShellModule.class})
+@Module(includes = {
+ DividerModule.class,
+ QSModule.class,
+ WindowManagerShellModule.class
+ },
+ subcomponents = {
+ SysUIComponent.class
+ })
public abstract class SystemUIDefaultModule {
@Singleton
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index fce545b421d5..f6db6d59bb6d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -26,6 +26,7 @@ import com.android.systemui.BootCompleteCacheImpl;
import com.android.systemui.assist.AssistModule;
import com.android.systemui.doze.dagger.DozeComponent;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.fragments.FragmentService;
import com.android.systemui.log.dagger.LogModule;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -38,6 +39,7 @@ import com.android.systemui.statusbar.notification.collection.inflation.Notifica
import com.android.systemui.statusbar.notification.people.PeopleHubModule;
import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
+import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent;
import com.android.systemui.statusbar.phone.KeyguardLiftController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
@@ -72,7 +74,9 @@ import dagger.Provides;
subcomponents = {StatusBarComponent.class,
NotificationRowComponent.class,
DozeComponent.class,
- ExpandableNotificationRowComponent.class})
+ ExpandableNotificationRowComponent.class,
+ NotificationShelfComponent.class,
+ FragmentService.FragmentCreator.class})
public abstract class SystemUIModule {
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
new file mode 100644
index 000000000000..929b61a3421c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
@@ -0,0 +1,35 @@
+/*
+ * 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.dagger;
+
+import dagger.Subcomponent;
+
+/**
+ * Dagger Subcomponent for WindowManager.
+ */
+@WMSingleton
+@Subcomponent(modules = {})
+public interface WMComponent {
+
+ /**
+ * Builder for a WMComponent.
+ */
+ @Subcomponent.Builder
+ interface Builder {
+ WMComponent build();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMModule.java b/packages/SystemUI/src/com/android/systemui/dagger/WMModule.java
new file mode 100644
index 000000000000..2894780e04b8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMModule.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 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.dagger;
+
+import dagger.Module;
+
+/**
+ * Dagger module for including the WMComponent.
+ */
+@Module(subcomponents = {WMComponent.class})
+public abstract class WMModule {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMSingleton.java b/packages/SystemUI/src/com/android/systemui/dagger/WMSingleton.java
new file mode 100644
index 000000000000..7292b9e459e0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMSingleton.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 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.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Scope;
+
+/**
+ * Scope annotation for singleton items within the WMComponent.
+ */
+@Documented
+@Retention(RUNTIME)
+@Scope
+public @interface WMSingleton {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index ae200763b3b0..0507592a89e1 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -21,7 +21,6 @@ import android.util.ArrayMap;
import android.view.View;
import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.SystemUIRootComponent;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.statusbar.phone.NavigationBarFragment;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -61,9 +60,9 @@ public class FragmentService implements Dumpable {
};
@Inject
- public FragmentService(SystemUIRootComponent rootComponent,
+ public FragmentService(FragmentCreator.Factory fragmentCreatorFactory,
ConfigurationController configurationController) {
- mFragmentCreator = rootComponent.createFragmentCreator();
+ mFragmentCreator = fragmentCreatorFactory.build();
initInjectionMap();
configurationController.addCallback(mConfigurationListener);
}
@@ -121,6 +120,11 @@ public class FragmentService implements Dumpable {
*/
@Subcomponent
public interface FragmentCreator {
+ /** Factory for creating a FragmentCreator. */
+ @Subcomponent.Factory
+ interface Factory {
+ FragmentCreator build();
+ }
/**
* Inject a NavigationBarFragment.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 3a37c0fd4634..daef2c506ad3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -52,7 +52,6 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUIAppComponentFactory;
-import com.android.systemui.SystemUIFactory;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.StatusBarState;
@@ -72,6 +71,9 @@ import javax.inject.Inject;
/**
* Simple Slice provider that shows the current date.
+ *
+ * Injection is handled by {@link SystemUIAppComponentFactory} +
+ * {@link com.android.systemui.dagger.GlobalRootComponent#inject(KeyguardSliceProvider)}.
*/
public class KeyguardSliceProvider extends SliceProvider implements
NextAlarmController.NextAlarmChangeCallback, ZenModeController.Callback,
@@ -298,7 +300,8 @@ public class KeyguardSliceProvider extends SliceProvider implements
@Override
public boolean onCreateSliceProvider() {
mContextAvailableCallback.onContextAvailable(getContext());
- inject();
+ mMediaWakeLock = new SettableWakeLock(WakeLock.createPartial(getContext(), "media"),
+ "media");
synchronized (KeyguardSliceProvider.sInstanceLock) {
KeyguardSliceProvider oldInstance = KeyguardSliceProvider.sInstance;
if (oldInstance != null) {
@@ -319,13 +322,6 @@ public class KeyguardSliceProvider extends SliceProvider implements
}
@VisibleForTesting
- protected void inject() {
- SystemUIFactory.getInstance().getRootComponent().inject(this);
- mMediaWakeLock = new SettableWakeLock(WakeLock.createPartial(getContext(), "media"),
- "media");
- }
-
- @VisibleForTesting
protected void onDestroy() {
synchronized (KeyguardSliceProvider.sInstanceLock) {
mNextAlarmController.removeCallback(this);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 75f4809d752f..d55ac7c7fc4b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -85,7 +85,6 @@ import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
-import com.android.systemui.SystemUIFactory;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.dump.DumpManager;
@@ -229,6 +228,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable {
/** TrustManager for letting it know when we change visibility */
private final TrustManager mTrustManager;
+ private final InjectionInflationController mInjectionInflationController;
/**
* Used to keep the device awake while to ensure the keyguard finishes opening before
@@ -723,7 +723,8 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable {
@UiBackground Executor uiBgExecutor, PowerManager powerManager,
TrustManager trustManager,
DeviceConfigProxy deviceConfig,
- NavigationModeController navigationModeController) {
+ NavigationModeController navigationModeController,
+ InjectionInflationController injectionInflationController) {
super(context);
mFalsingManager = falsingManager;
mLockPatternUtils = lockPatternUtils;
@@ -734,6 +735,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable {
mUpdateMonitor = keyguardUpdateMonitor;
mPM = powerManager;
mTrustManager = trustManager;
+ mInjectionInflationController = injectionInflationController;
dumpManager.registerDumpable(getClass().getName(), this);
mDeviceConfig = deviceConfig;
mShowHomeOverLockscreen = mDeviceConfig.getBoolean(
@@ -773,10 +775,8 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable {
mContext.registerReceiver(mDelayedLockBroadcastReceiver, delayedActionFilter,
SYSTEMUI_PERMISSION, null /* scheduler */);
- InjectionInflationController injectionInflationController =
- new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent());
mKeyguardDisplayManager = new KeyguardDisplayManager(mContext,
- injectionInflationController);
+ mInjectionInflationController);
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 83c95b77b716..ab41afb5a831 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -32,6 +32,7 @@ import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.NavigationModeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.util.DeviceConfigProxy;
+import com.android.systemui.util.InjectionInflationController;
import java.util.concurrent.Executor;
@@ -64,7 +65,8 @@ public class KeyguardModule {
TrustManager trustManager,
@UiBackground Executor uiBgExecutor,
DeviceConfigProxy deviceConfig,
- NavigationModeController navigationModeController) {
+ NavigationModeController navigationModeController,
+ InjectionInflationController injectionInflationController) {
return new KeyguardViewMediator(
context,
falsingManager,
@@ -78,6 +80,7 @@ public class KeyguardModule {
powerManager,
trustManager,
deviceConfig,
- navigationModeController);
+ navigationModeController,
+ injectionInflationController);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index 7f610d1a8467..b993faabe9b1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -10,6 +10,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
+import androidx.annotation.VisibleForTesting
import com.android.systemui.R
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
@@ -21,6 +22,7 @@ import com.android.systemui.util.Utils
import com.android.systemui.util.animation.UniqueObjectHostView
import com.android.systemui.util.animation.requiresRemeasuring
import com.android.systemui.util.concurrency.DelayableExecutor
+import java.util.TreeMap
import javax.inject.Inject
import javax.inject.Provider
import javax.inject.Singleton
@@ -102,9 +104,7 @@ class MediaCarouselController @Inject constructor(
private val mediaCarousel: MediaScrollView
private val mediaCarouselScrollHandler: MediaCarouselScrollHandler
val mediaFrame: ViewGroup
- val mediaPlayers: MutableMap<String, MediaControlPanel> = mutableMapOf()
private lateinit var settingsButton: View
- private val mediaData: MutableMap<String, MediaData> = mutableMapOf()
private val mediaContent: ViewGroup
private val pageIndicator: PageIndicator
private val visualStabilityCallback: VisualStabilityManager.Callback
@@ -122,7 +122,7 @@ class MediaCarouselController @Inject constructor(
set(value) {
if (field != value) {
field = value
- for (player in mediaPlayers.values) {
+ for (player in MediaPlayerData.players()) {
player.setListening(field)
}
}
@@ -167,20 +167,18 @@ class MediaCarouselController @Inject constructor(
true /* persistent */)
mediaManager.addListener(object : MediaDataManager.Listener {
override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) {
- oldKey?.let { mediaData.remove(it) }
if (!data.active && !Utils.useMediaResumption(context)) {
// This view is inactive, let's remove this! This happens e.g when dismissing /
// timing out a view. We still have the data around because resumption could
// be on, but we should save the resources and release this.
+ oldKey?.let { MediaPlayerData.removeMediaPlayer(it) }
onMediaDataRemoved(key)
} else {
- mediaData.put(key, data)
addOrUpdatePlayer(key, oldKey, data)
}
}
override fun onMediaDataRemoved(key: String) {
- mediaData.remove(key)
removePlayer(key)
}
})
@@ -223,53 +221,36 @@ class MediaCarouselController @Inject constructor(
}
private fun reorderAllPlayers() {
- for (mediaPlayer in mediaPlayers.values) {
- val view = mediaPlayer.view?.player
- if (mediaPlayer.isPlaying && mediaContent.indexOfChild(view) != 0) {
- mediaContent.removeView(view)
- mediaContent.addView(view, 0)
+ mediaContent.removeAllViews()
+ for (mediaPlayer in MediaPlayerData.players()) {
+ mediaPlayer.view?.let {
+ mediaContent.addView(it.player)
}
}
mediaCarouselScrollHandler.onPlayersChanged()
}
private fun addOrUpdatePlayer(key: String, oldKey: String?, data: MediaData) {
- // If the key was changed, update entry
- val oldData = mediaPlayers[oldKey]
- if (oldData != null) {
- val oldData = mediaPlayers.remove(oldKey)
- mediaPlayers.put(key, oldData!!)?.let {
- Log.wtf(TAG, "new key $key already exists when migrating from $oldKey")
- }
- }
- var existingPlayer = mediaPlayers[key]
+ val existingPlayer = MediaPlayerData.getMediaPlayer(key, oldKey)
if (existingPlayer == null) {
- existingPlayer = mediaControlPanelFactory.get()
- existingPlayer.attach(PlayerViewHolder.create(LayoutInflater.from(context),
- mediaContent))
- existingPlayer.mediaViewController.sizeChangedListener = this::updateCarouselDimensions
- mediaPlayers[key] = existingPlayer
+ var newPlayer = mediaControlPanelFactory.get()
+ newPlayer.attach(PlayerViewHolder.create(LayoutInflater.from(context), mediaContent))
+ newPlayer.mediaViewController.sizeChangedListener = this::updateCarouselDimensions
+ MediaPlayerData.addMediaPlayer(key, data, newPlayer)
val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT)
- existingPlayer.view?.player?.setLayoutParams(lp)
- existingPlayer.bind(data)
- existingPlayer.setListening(currentlyExpanded)
- updatePlayerToState(existingPlayer, noAnimation = true)
- if (existingPlayer.isPlaying) {
- mediaContent.addView(existingPlayer.view?.player, 0)
- } else {
- mediaContent.addView(existingPlayer.view?.player)
- }
+ newPlayer.view?.player?.setLayoutParams(lp)
+ newPlayer.bind(data)
+ newPlayer.setListening(currentlyExpanded)
+ updatePlayerToState(newPlayer, noAnimation = true)
+ reorderAllPlayers()
} else {
existingPlayer.bind(data)
- if (existingPlayer.isPlaying &&
- mediaContent.indexOfChild(existingPlayer.view?.player) != 0) {
- if (visualStabilityManager.isReorderingAllowed) {
- mediaContent.removeView(existingPlayer.view?.player)
- mediaContent.addView(existingPlayer.view?.player, 0)
- } else {
- needsReordering = true
- }
+ MediaPlayerData.addMediaPlayer(key, data, existingPlayer)
+ if (visualStabilityManager.isReorderingAllowed) {
+ reorderAllPlayers()
+ } else {
+ needsReordering = true
}
}
updatePageIndicator()
@@ -277,13 +258,13 @@ class MediaCarouselController @Inject constructor(
mediaCarousel.requiresRemeasuring = true
// Check postcondition: mediaContent should have the same number of children as there are
// elements in mediaPlayers.
- if (mediaPlayers.size != mediaContent.childCount) {
+ if (MediaPlayerData.players().size != mediaContent.childCount) {
Log.wtf(TAG, "Size of players list and number of views in carousel are out of sync")
}
}
private fun removePlayer(key: String) {
- val removed = mediaPlayers.remove(key)
+ val removed = MediaPlayerData.removeMediaPlayer(key)
removed?.apply {
mediaCarouselScrollHandler.onPrePlayerRemoved(removed)
mediaContent.removeView(removed.view?.player)
@@ -294,12 +275,7 @@ class MediaCarouselController @Inject constructor(
}
private fun recreatePlayers() {
- // Note that this will scramble the order of players. Actively playing sessions will, at
- // least, still be put in the front. If we want to maintain order, then more work is
- // needed.
- mediaData.forEach {
- key, data ->
- removePlayer(key)
+ MediaPlayerData.mediaData().forEach { (key, data) ->
addOrUpdatePlayer(key = key, oldKey = null, data = data)
}
}
@@ -337,7 +313,7 @@ class MediaCarouselController @Inject constructor(
currentStartLocation = startLocation
currentEndLocation = endLocation
currentTransitionProgress = progress
- for (mediaPlayer in mediaPlayers.values) {
+ for (mediaPlayer in MediaPlayerData.players()) {
updatePlayerToState(mediaPlayer, immediately)
}
maybeResetSettingsCog()
@@ -386,7 +362,7 @@ class MediaCarouselController @Inject constructor(
private fun updateCarouselDimensions() {
var width = 0
var height = 0
- for (mediaPlayer in mediaPlayers.values) {
+ for (mediaPlayer in MediaPlayerData.players()) {
val controller = mediaPlayer.mediaViewController
// When transitioning the view to gone, the view gets smaller, but the translation
// Doesn't, let's add the translation
@@ -448,7 +424,7 @@ class MediaCarouselController @Inject constructor(
this.desiredLocation = desiredLocation
this.desiredHostState = it
currentlyExpanded = it.expansion > 0
- for (mediaPlayer in mediaPlayers.values) {
+ for (mediaPlayer in MediaPlayerData.players()) {
if (animate) {
mediaPlayer.mediaViewController.animatePendingStateChange(
duration = duration,
@@ -470,7 +446,7 @@ class MediaCarouselController @Inject constructor(
}
fun closeGuts() {
- mediaPlayers.values.forEach {
+ MediaPlayerData.players().forEach {
it.closeGuts(true)
}
}
@@ -497,3 +473,50 @@ class MediaCarouselController @Inject constructor(
}
}
}
+
+@VisibleForTesting
+internal object MediaPlayerData {
+ private data class MediaSortKey(
+ val data: MediaData,
+ val updateTime: Long = 0,
+ val isPlaying: Boolean = false
+ )
+
+ private val comparator =
+ compareByDescending<MediaSortKey> { it.isPlaying }
+ .thenByDescending { it.data.isLocalSession }
+ .thenByDescending { !it.data.resumption }
+ .thenByDescending { it.updateTime }
+
+ private val mediaPlayers = TreeMap<MediaSortKey, MediaControlPanel>(comparator)
+ private val mediaData: MutableMap<String, MediaSortKey> = mutableMapOf()
+
+ fun addMediaPlayer(key: String, data: MediaData, player: MediaControlPanel) {
+ removeMediaPlayer(key)
+ val sortKey = MediaSortKey(data, System.currentTimeMillis(), player.isPlaying())
+ mediaData.put(key, sortKey)
+ mediaPlayers.put(sortKey, player)
+ }
+
+ fun getMediaPlayer(key: String, oldKey: String?): MediaControlPanel? {
+ // If the key was changed, update entry
+ oldKey?.let {
+ if (it != key) {
+ mediaData.remove(it)?.let { sortKey -> mediaData.put(key, sortKey) }
+ }
+ }
+ return mediaData.get(key)?.let { mediaPlayers.get(it) }
+ }
+
+ fun removeMediaPlayer(key: String) = mediaData.remove(key)?.let { mediaPlayers.remove(it) }
+
+ fun mediaData() = mediaData.entries.map { e -> Pair(e.key, e.value.data) }
+
+ fun players() = mediaPlayers.values
+
+ @VisibleForTesting
+ fun clear() {
+ mediaData.clear()
+ mediaPlayers.clear()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
index dafc52ad8025..d6a02687c905 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
@@ -82,6 +82,10 @@ data class MediaData(
*/
var resumeAction: Runnable?,
/**
+ * Local or remote playback
+ */
+ var isLocalSession: Boolean = true,
+ /**
* Indicates that this player is a resumption player (ie. It only shows a play actions which
* will start the app and start playing).
*/
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 8a51c8515852..30e10f655026 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -31,6 +31,7 @@ import android.graphics.drawable.Drawable
import android.graphics.drawable.Icon
import android.media.MediaDescription
import android.media.MediaMetadata
+import android.media.session.MediaController
import android.media.session.MediaSession
import android.net.Uri
import android.os.UserHandle
@@ -44,6 +45,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
+import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.notification.MediaNotificationProcessor
import com.android.systemui.statusbar.notification.row.HybridGroupManager
import com.android.systemui.util.Assert
@@ -97,6 +99,7 @@ class MediaDataManager(
dumpManager: DumpManager,
mediaTimeoutListener: MediaTimeoutListener,
mediaResumeListener: MediaResumeListener,
+ private val activityStarter: ActivityStarter,
private var useMediaResumption: Boolean,
private val useQsMediaPlayer: Boolean
) : Dumpable {
@@ -113,10 +116,11 @@ class MediaDataManager(
dumpManager: DumpManager,
broadcastDispatcher: BroadcastDispatcher,
mediaTimeoutListener: MediaTimeoutListener,
- mediaResumeListener: MediaResumeListener
+ mediaResumeListener: MediaResumeListener,
+ activityStarter: ActivityStarter
) : this(context, backgroundExecutor, foregroundExecutor, mediaControllerFactory,
broadcastDispatcher, dumpManager, mediaTimeoutListener, mediaResumeListener,
- Utils.useMediaResumption(context), Utils.useQsMediaPlayer(context))
+ activityStarter, Utils.useMediaResumption(context), Utils.useQsMediaPlayer(context))
private val appChangeReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
@@ -328,7 +332,8 @@ class MediaDataManager(
) {
val token = sbn.notification.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION)
as MediaSession.Token?
- val metadata = mediaControllerFactory.create(token).metadata
+ val mediaController = mediaControllerFactory.create(token)
+ val metadata = mediaController.metadata
// Foreground and Background colors computed from album art
val notif: Notification = sbn.notification
@@ -403,10 +408,13 @@ class MediaDataManager(
}
val runnable = if (action.actionIntent != null) {
Runnable {
- try {
- action.actionIntent.send()
- } catch (e: PendingIntent.CanceledException) {
- Log.d(TAG, "Intent canceled", e)
+ if (action.isAuthenticationRequired()) {
+ activityStarter.dismissKeyguardThenExecute ({
+ var result = sendPendingIntent(action.actionIntent)
+ result
+ }, {}, true)
+ } else {
+ sendPendingIntent(action.actionIntent)
}
}
} else {
@@ -420,6 +428,9 @@ class MediaDataManager(
}
}
+ val isLocalSession = mediaController.playbackInfo?.playbackType ==
+ MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL ?: true
+
foregroundExecutor.execute {
val resumeAction: Runnable? = mediaEntries[key]?.resumeAction
val hasCheckedForResume = mediaEntries[key]?.hasCheckedForResume == true
@@ -427,8 +438,8 @@ class MediaDataManager(
onMediaDataLoaded(key, oldKey, MediaData(sbn.normalizedUserId, true, bgColor, app,
smallIconDrawable, artist, song, artWorkIcon, actionIcons,
actionsToShowCollapsed, sbn.packageName, token, notif.contentIntent, null,
- active, resumeAction = resumeAction, notificationKey = key,
- hasCheckedForResume = hasCheckedForResume))
+ active, resumeAction = resumeAction, isLocalSession = isLocalSession,
+ notificationKey = key, hasCheckedForResume = hasCheckedForResume))
}
}
@@ -449,6 +460,15 @@ class MediaDataManager(
return null
}
+ private fun sendPendingIntent(intent: PendingIntent): Boolean {
+ return try {
+ intent.send()
+ true
+ } catch (e: PendingIntent.CanceledException) {
+ Log.d(TAG, "Intent canceled", e)
+ false
+ }
+ }
/**
* Load a bitmap from a URI
* @param uri the uri to load
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java
index 8550959aa2c4..2e91697de849 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java
@@ -26,6 +26,7 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Looper;
+import android.os.SystemProperties;
import android.util.Log;
import android.view.SurfaceControl;
import android.window.DisplayAreaInfo;
@@ -61,6 +62,8 @@ import javax.inject.Inject;
*/
public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implements Dumpable {
private static final String TAG = "OneHandedDisplayAreaOrganizer";
+ private static final String ONE_HANDED_MODE_TRANSLATE_ANIMATION_DURATION =
+ "persist.debug.one_handed_translate_animation_duration";
@VisibleForTesting
static final int MSG_RESET_IMMEDIATE = 1;
@@ -156,8 +159,8 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen
mDisplayController = displayController;
mDefaultDisplayBounds.set(getDisplayBounds());
mLastVisualDisplayBounds.set(getDisplayBounds());
- mEnterExitAnimationDurationMs = context.getResources().getInteger(
- com.android.systemui.R.integer.config_one_handed_translate_animation_duration);
+ mEnterExitAnimationDurationMs =
+ SystemProperties.getInt(ONE_HANDED_MODE_TRANSLATE_ANIMATION_DURATION, 300);
mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
mTutorialHandler = tutorialHandler;
}
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java
index a3921ee54fec..42524bb33818 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java
@@ -24,13 +24,13 @@ import android.content.ComponentName;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
+import android.os.SystemProperties;
import android.view.KeyEvent;
import androidx.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dumpable;
-import com.android.systemui.R;
import com.android.systemui.model.SysUiState;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
@@ -50,6 +50,8 @@ import javax.inject.Singleton;
@Singleton
public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
private static final String TAG = "OneHandedManager";
+ private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE =
+ "persist.debug.one_handed_offset_percentage";
private boolean mIsOneHandedEnabled;
private boolean mIsSwipeToNotificationEnabled;
@@ -117,8 +119,8 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
mDisplayController = displayController;
mDisplayController.addDisplayChangingController(mRotationController);
mSysUiFlagContainer = sysUiState;
- mOffSetFraction =
- context.getResources().getFraction(R.fraction.config_one_handed_offset, 1, 1);
+ mOffSetFraction = SystemProperties.getInt(ONE_HANDED_MODE_OFFSET_PERCENTAGE, 50) / 100.0f;
+
mIsOneHandedEnabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
context.getContentResolver());
mIsSwipeToNotificationEnabled = OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
index b28730d004f6..de34b2ec831d 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
@@ -22,6 +22,7 @@ import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Handler;
+import android.os.SystemProperties;
import android.provider.Settings;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -50,6 +51,8 @@ import javax.inject.Singleton;
@Singleton
public class OneHandedTutorialHandler implements OneHandedTransitionCallback, Dumpable {
private static final String TAG = "OneHandedTutorialHandler";
+ private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE =
+ "persist.debug.one_handed_offset_percentage";
private static final int MAX_TUTORIAL_SHOW_COUNT = 2;
private final Rect mLastUpdatedBounds = new Rect();
private final WindowManager mWindowManager;
@@ -81,8 +84,8 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback, Du
mWindowManager = context.getSystemService(WindowManager.class);
mTargetViewContainer = new FrameLayout(context);
mTargetViewContainer.setClipChildren(false);
- mTutorialAreaHeight = Math.round(mDisplaySize.y * context.getResources().getFraction(
- R.fraction.config_one_handed_offset, 1, 1));
+ mTutorialAreaHeight = Math.round(mDisplaySize.y
+ * (SystemProperties.getInt(ONE_HANDED_MODE_OFFSET_PERCENTAGE, 50) / 100.0f));
mTutorialView = LayoutInflater.from(context).inflate(R.xml.one_handed_tutorial, null);
mTargetViewContainer.addView(mTutorialView);
mCanShowTutorial = (Settings.Secure.getInt(mContentResolver,
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 01670285c0f4..f1c8b0cf0e42 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -186,20 +186,23 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
private class PipManagerPinnedStackListener extends PinnedStackListener {
@Override
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
- if (mState == STATE_PIP) {
- if (mImeVisible != imeVisible) {
- if (imeVisible) {
- // Save the IME height adjustment, and offset to not occlude the IME
- mPipBounds.offset(0, -imeHeight);
- mImeHeightAdjustment = imeHeight;
- } else {
- // Apply the inverse adjustment when the IME is hidden
- mPipBounds.offset(0, mImeHeightAdjustment);
+ mHandler.post(() -> {
+ mPipBoundsHandler.onImeVisibilityChanged(imeVisible, imeHeight);
+ if (mState == STATE_PIP) {
+ if (mImeVisible != imeVisible) {
+ if (imeVisible) {
+ // Save the IME height adjustment, and offset to not occlude the IME
+ mPipBounds.offset(0, -imeHeight);
+ mImeHeightAdjustment = imeHeight;
+ } else {
+ // Apply the inverse adjustment when the IME is hidden
+ mPipBounds.offset(0, mImeHeightAdjustment);
+ }
+ mImeVisible = imeVisible;
+ resizePinnedStack(STATE_PIP);
}
- mImeVisible = imeVisible;
- resizePinnedStack(STATE_PIP);
}
- }
+ });
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
index f8655cc44d2a..52a2cecec6b1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java
@@ -3,7 +3,9 @@ package com.android.systemui.qs;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
+import android.graphics.drawable.Animatable2;
import android.graphics.drawable.AnimatedVectorDrawable;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@@ -44,6 +46,24 @@ public class PageIndicator extends ViewGroup {
private int mPosition = -1;
private boolean mAnimating;
+ private final Animatable2.AnimationCallback mAnimationCallback =
+ new Animatable2.AnimationCallback() {
+
+ @Override
+ public void onAnimationEnd(Drawable drawable) {
+ super.onAnimationEnd(drawable);
+ if (DEBUG) Log.d(TAG, "onAnimationEnd - queued: " + mQueuedPositions.size());
+ if (drawable instanceof AnimatedVectorDrawable) {
+ ((AnimatedVectorDrawable) drawable).unregisterAnimationCallback(
+ mAnimationCallback);
+ }
+ mAnimating = false;
+ if (mQueuedPositions.size() != 0) {
+ setPosition(mQueuedPositions.remove(0));
+ }
+ }
+ };
+
public PageIndicator(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -197,10 +217,8 @@ public class PageIndicator extends ViewGroup {
final AnimatedVectorDrawable avd = (AnimatedVectorDrawable) getContext().getDrawable(res);
imageView.setImageDrawable(avd);
avd.forceAnimationOnUI();
+ avd.registerAnimationCallback(mAnimationCallback);
avd.start();
- // TODO: Figure out how to user an AVD animation callback instead, which doesn't
- // seem to be working right now...
- postDelayed(mAnimationDone, ANIMATION_DURATION);
}
private int getTransition(boolean fromB, boolean isMajorAState, boolean isMajor) {
@@ -264,15 +282,4 @@ public class PageIndicator extends ViewGroup {
getChildAt(i).layout(left, 0, mPageIndicatorWidth + left, mPageIndicatorHeight);
}
}
-
- private final Runnable mAnimationDone = new Runnable() {
- @Override
- public void run() {
- if (DEBUG) Log.d(TAG, "onAnimationEnd - queued: " + mQueuedPositions.size());
- mAnimating = false;
- if (mQueuedPositions.size() != 0) {
- setPosition(mQueuedPositions.remove(0));
- }
- }
- };
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index c53523032353..6747281ac437 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -50,6 +50,7 @@ import android.graphics.drawable.LayerDrawable;
import android.media.MediaActionSound;
import android.net.Uri;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
@@ -556,11 +557,18 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
private void takeScreenshotInternal(Consumer<Uri> finisher, Rect crop) {
// copy the input Rect, since SurfaceControl.screenshot can mutate it
Rect screenRect = new Rect(crop);
- int rot = mDisplay.getRotation();
int width = crop.width();
int height = crop.height();
- saveScreenshot(SurfaceControl.screenshot(crop, width, height, rot), finisher, screenRect,
- Insets.NONE, true);
+ final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
+ final SurfaceControl.DisplayCaptureArgs captureArgs =
+ new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
+ .setSourceCrop(crop)
+ .setSize(width, height)
+ .build();
+ final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
+ SurfaceControl.captureDisplay(captureArgs);
+ final Bitmap screenshot = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
+ saveScreenshot(screenshot, finisher, screenRect, Insets.NONE, true);
}
private void saveScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index 6b023c07b1a6..95867957f648 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -161,7 +161,9 @@ public class NotificationRemoteInputManager implements Dumpable {
ActivityManager.getService().resumeAppSwitches();
} catch (RemoteException e) {
}
- return mCallback.handleRemoteViewClick(view, pendingIntent, () -> {
+ Notification.Action action = getActionFromView(view, entry, pendingIntent);
+ return mCallback.handleRemoteViewClick(view, pendingIntent,
+ action == null ? false : action.isAuthenticationRequired(), () -> {
Pair<Intent, ActivityOptions> options = response.getLaunchOptions(view);
options.second.setLaunchWindowingMode(
WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
@@ -170,47 +172,56 @@ public class NotificationRemoteInputManager implements Dumpable {
});
}
- private void logActionClick(
- View view,
- NotificationEntry entry,
- PendingIntent actionIntent) {
+ private @Nullable Notification.Action getActionFromView(View view,
+ NotificationEntry entry, PendingIntent actionIntent) {
Integer actionIndex = (Integer)
view.getTag(com.android.internal.R.id.notification_action_index_tag);
if (actionIndex == null) {
- // Custom action button, not logging.
- return;
+ return null;
}
- ViewParent parent = view.getParent();
if (entry == null) {
Log.w(TAG, "Couldn't determine notification for click.");
- return;
- }
- StatusBarNotification statusBarNotification = entry.getSbn();
- String key = statusBarNotification.getKey();
- int buttonIndex = -1;
- // If this is a default template, determine the index of the button.
- if (view.getId() == com.android.internal.R.id.action0 &&
- parent != null && parent instanceof ViewGroup) {
- ViewGroup actionGroup = (ViewGroup) parent;
- buttonIndex = actionGroup.indexOfChild(view);
+ return null;
}
- final int count = mEntryManager.getActiveNotificationsCount();
- final int rank = mEntryManager
- .getActiveNotificationUnfiltered(key).getRanking().getRank();
// Notification may be updated before this function is executed, and thus play safe
// here and verify that the action object is still the one that where the click happens.
+ StatusBarNotification statusBarNotification = entry.getSbn();
Notification.Action[] actions = statusBarNotification.getNotification().actions;
if (actions == null || actionIndex >= actions.length) {
Log.w(TAG, "statusBarNotification.getNotification().actions is null or invalid");
- return;
+ return null ;
}
final Notification.Action action =
statusBarNotification.getNotification().actions[actionIndex];
if (!Objects.equals(action.actionIntent, actionIntent)) {
Log.w(TAG, "actionIntent does not match");
+ return null;
+ }
+ return action;
+ }
+
+ private void logActionClick(
+ View view,
+ NotificationEntry entry,
+ PendingIntent actionIntent) {
+ Notification.Action action = getActionFromView(view, entry, actionIntent);
+ if (action == null) {
return;
}
+ ViewParent parent = view.getParent();
+ String key = entry.getSbn().getKey();
+ int buttonIndex = -1;
+ // If this is a default template, determine the index of the button.
+ if (view.getId() == com.android.internal.R.id.action0 &&
+ parent != null && parent instanceof ViewGroup) {
+ ViewGroup actionGroup = (ViewGroup) parent;
+ buttonIndex = actionGroup.indexOfChild(view);
+ }
+ final int count = mEntryManager.getActiveNotificationsCount();
+ final int rank = mEntryManager
+ .getActiveNotificationUnfiltered(key).getRanking().getRank();
+
NotificationVisibility.NotificationLocation location =
NotificationLogger.getNotificationLocation(
mEntryManager.getActiveNotificationUnfiltered(key));
@@ -813,11 +824,12 @@ public class NotificationRemoteInputManager implements Dumpable {
*
* @param view
* @param pendingIntent
+ * @param appRequestedAuth
* @param defaultHandler
* @return true iff the click was handled
*/
boolean handleRemoteViewClick(View view, PendingIntent pendingIntent,
- ClickHandler defaultHandler);
+ boolean appRequestedAuth, ClickHandler defaultHandler);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index d798692879f5..8f3033edecbb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -18,7 +18,6 @@ package com.android.systemui.statusbar;
import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN_REVERSE;
import static com.android.systemui.statusbar.phone.NotificationIconContainer.IconState.NO_VALUE;
-import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
import android.content.Context;
import android.content.res.Configuration;
@@ -26,7 +25,6 @@ import android.content.res.Resources;
import android.graphics.Rect;
import android.os.SystemProperties;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.MathUtils;
import android.view.DisplayCutout;
import android.view.View;
@@ -36,10 +34,8 @@ import android.view.WindowInsets;
import android.view.accessibility.AccessibilityNodeInfo;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -48,14 +44,10 @@ import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.notification.stack.ViewState;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
-import javax.inject.Inject;
-import javax.inject.Named;
-
/**
* A notification shelf view that is placed inside the notification scroller. It manages the
* overflow icons that don't fit into the regular list anymore.
@@ -69,7 +61,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
= SystemProperties.getBoolean("debug.icon_scroll_animations", true);
private static final int TAG_CONTINUOUS_CLIPPING = R.id.continuous_clipping_tag;
private static final String TAG = "NotificationShelf";
- private final KeyguardBypassController mBypassController;
private NotificationIconContainer mShelfIcons;
private int[] mTmp = new int[2];
@@ -77,9 +68,8 @@ public class NotificationShelf extends ActivatableNotificationView implements
private int mIconAppearTopPadding;
private float mHiddenShelfIconSize;
private int mStatusBarHeight;
- private int mStatusBarPaddingStart;
private AmbientState mAmbientState;
- private NotificationStackScrollLayout mHostLayout;
+ private NotificationStackScrollLayoutController mHostLayoutController;
private int mMaxLayoutHeight;
private int mPaddingBetweenElements;
private int mNotGoneIndex;
@@ -88,7 +78,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
private int mScrollFastThreshold;
private int mIconSize;
private int mStatusBarState;
- private float mMaxShelfEnd;
private int mRelativeOffset;
private boolean mInteractive;
private float mOpenedAmount;
@@ -99,13 +88,10 @@ public class NotificationShelf extends ActivatableNotificationView implements
private Rect mClipRect = new Rect();
private int mCutoutHeight;
private int mGapHeight;
+ private NotificationShelfController mController;
- @Inject
- public NotificationShelf(@Named(VIEW_CONTEXT) Context context,
- AttributeSet attrs,
- KeyguardBypassController keyguardBypassController) {
+ public NotificationShelf(Context context, AttributeSet attrs) {
super(context, attrs);
- mBypassController = keyguardBypassController;
}
@Override
@@ -128,29 +114,16 @@ public class NotificationShelf extends ActivatableNotificationView implements
initDimens();
}
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- ((SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class))
- .addCallback(this, SysuiStatusBarStateController.RANK_SHELF);
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- Dependency.get(StatusBarStateController.class).removeCallback(this);
- }
-
- public void bind(AmbientState ambientState, NotificationStackScrollLayout hostLayout) {
+ public void bind(AmbientState ambientState,
+ NotificationStackScrollLayoutController hostLayoutController) {
mAmbientState = ambientState;
- mHostLayout = hostLayout;
+ mHostLayoutController = hostLayoutController;
}
private void initDimens() {
Resources res = getResources();
mIconAppearTopPadding = res.getDimensionPixelSize(R.dimen.notification_icon_appear_padding);
mStatusBarHeight = res.getDimensionPixelOffset(R.dimen.status_bar_height);
- mStatusBarPaddingStart = res.getDimensionPixelOffset(R.dimen.status_bar_padding_start);
mPaddingBetweenElements = res.getDimensionPixelSize(R.dimen.notification_divider_height);
ViewGroup.LayoutParams layoutParams = getLayoutParams();
@@ -276,8 +249,8 @@ public class NotificationShelf extends ActivatableNotificationView implements
float firstElementRoundness = 0.0f;
ActivatableNotificationView previousAnv = null;
- for (int i = 0; i < mHostLayout.getChildCount(); i++) {
- ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
+ for (int i = 0; i < mHostLayoutController.getChildCount(); i++) {
+ ExpandableView child = (ExpandableView) mHostLayoutController.getChildAt(i);
if (!child.needsClippingToShelf() || child.getVisibility() == GONE) {
continue;
@@ -315,9 +288,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
transitionAmount = inShelfAmount;
}
// We don't want to modify the color if the notification is hun'd
- boolean canModifyColor = mAmbientState.isShadeExpanded()
- && !(mAmbientState.isOnKeyguard() && mBypassController.getBypassEnabled());
- if (isLastChild && canModifyColor) {
+ if (isLastChild && mController.canModifyColorOfNotifications()) {
if (colorOfViewBeforeLast == NO_COLOR) {
colorOfViewBeforeLast = ownColorUntinted;
}
@@ -384,8 +355,8 @@ public class NotificationShelf extends ActivatableNotificationView implements
mShelfIcons.setSpeedBumpIndex(mAmbientState.getSpeedBumpIndex());
mShelfIcons.calculateIconTranslations();
mShelfIcons.applyIconStates();
- for (int i = 0; i < mHostLayout.getChildCount(); i++) {
- View child = mHostLayout.getChildAt(i);
+ for (int i = 0; i < mHostLayoutController.getChildCount(); i++) {
+ View child = mHostLayoutController.getChildAt(i);
if (!(child instanceof ExpandableNotificationRow)
|| child.getVisibility() == GONE) {
continue;
@@ -408,8 +379,8 @@ public class NotificationShelf extends ActivatableNotificationView implements
* swipes quickly.
*/
private void clipTransientViews() {
- for (int i = 0; i < mHostLayout.getTransientViewCount(); i++) {
- View transientView = mHostLayout.getTransientView(i);
+ for (int i = 0; i < mHostLayoutController.getTransientViewCount(); i++) {
+ View transientView = mHostLayoutController.getTransientView(i);
if (transientView instanceof ExpandableView) {
ExpandableView transientExpandableView = (ExpandableView) transientView;
updateNotificationClipHeight(transientExpandableView, getTranslationY(), -1);
@@ -648,7 +619,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
// We need to persist this, since after the expansion, the behavior should still be the
// same.
float position = mAmbientState.getIntrinsicPadding()
- + mHostLayout.getPositionInLinearLayout(view);
+ + mHostLayoutController.getPositionInLinearLayout(view);
int maxShelfStart = mMaxLayoutHeight - getIntrinsicHeight();
if (position < maxShelfStart && position + view.getIntrinsicHeight() >= maxShelfStart
&& view.getTranslationY() < position) {
@@ -999,10 +970,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
return mInteractive;
}
- public void setMaxShelfEnd(float maxShelfEnd) {
- mMaxShelfEnd = maxShelfEnd;
- }
-
public void setAnimationsEnabled(boolean enabled) {
mAnimationsEnabled = enabled;
if (!enabled) {
@@ -1044,6 +1011,10 @@ public class NotificationShelf extends ActivatableNotificationView implements
updateBackgroundColors();
}
+ public void setController(NotificationShelfController notificationShelfController) {
+ mController = notificationShelfController;
+ }
+
private class ShelfState extends ExpandableViewState {
private float openedAmount;
private boolean hasItemsInStableShelf;
@@ -1056,7 +1027,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
}
super.applyToView(view);
- setMaxShelfEnd(maxShelfEnd);
setOpenedAmount(openedAmount);
updateAppearance();
setHasItemsInStableShelf(hasItemsInStableShelf);
@@ -1070,7 +1040,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
}
super.animateTo(child, properties);
- setMaxShelfEnd(maxShelfEnd);
setOpenedAmount(openedAmount);
updateAppearance();
setHasItemsInStableShelf(hasItemsInStableShelf);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelfController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelfController.java
new file mode 100644
index 000000000000..77abcfa848ee
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelfController.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2020 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.view.View;
+
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController;
+import com.android.systemui.statusbar.notification.row.dagger.NotificationRowScope;
+import com.android.systemui.statusbar.notification.stack.AmbientState;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.NotificationIconContainer;
+import com.android.systemui.statusbar.phone.StatusBarNotificationPresenter;
+
+import javax.inject.Inject;
+
+/**
+ * Controller class for {@link NotificationShelf}.
+ */
+@NotificationRowScope
+public class NotificationShelfController {
+ private final NotificationShelf mView;
+ private final ActivatableNotificationViewController mActivatableNotificationViewController;
+ private final KeyguardBypassController mKeyguardBypassController;
+ private final SysuiStatusBarStateController mStatusBarStateController;
+ private final View.OnAttachStateChangeListener mOnAttachStateChangeListener;
+ private AmbientState mAmbientState;
+
+ @Inject
+ public NotificationShelfController(NotificationShelf notificationShelf,
+ ActivatableNotificationViewController activatableNotificationViewController,
+ KeyguardBypassController keyguardBypassController,
+ SysuiStatusBarStateController statusBarStateController) {
+ mView = notificationShelf;
+ mActivatableNotificationViewController = activatableNotificationViewController;
+ mKeyguardBypassController = keyguardBypassController;
+ mStatusBarStateController = statusBarStateController;
+ mOnAttachStateChangeListener = new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ mStatusBarStateController.addCallback(
+ mView, SysuiStatusBarStateController.RANK_SHELF);
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ mStatusBarStateController.removeCallback(mView);
+ }
+ };
+ }
+
+ public void init() {
+ mActivatableNotificationViewController.init();
+ mView.setController(this);
+ mView.addOnAttachStateChangeListener(mOnAttachStateChangeListener);
+ if (mView.isAttachedToWindow()) {
+ mOnAttachStateChangeListener.onViewAttachedToWindow(mView);
+ }
+ }
+
+ public NotificationShelf getView() {
+ return mView;
+ }
+
+ public boolean canModifyColorOfNotifications() {
+ return mAmbientState.isShadeExpanded()
+ && !(mAmbientState.isOnKeyguard() && mKeyguardBypassController.getBypassEnabled());
+ }
+
+ public NotificationIconContainer getShelfIcons() {
+ return mView.getShelfIcons();
+ }
+
+ public void setCollapsedIcons(NotificationIconContainer notificationIcons) {
+ mView.setCollapsedIcons(notificationIcons);
+ }
+
+ public void bind(AmbientState ambientState,
+ NotificationStackScrollLayoutController notificationStackScrollLayoutController) {
+ mView.bind(ambientState, notificationStackScrollLayoutController);
+ mAmbientState = ambientState;
+ }
+
+ public int getHeight() {
+ return mView.getHeight();
+ }
+
+ public void updateState(AmbientState ambientState) {
+ mAmbientState = ambientState;
+ mView.updateState(ambientState);
+ }
+
+ public int getIntrinsicHeight() {
+ return mView.getIntrinsicHeight();
+ }
+
+ public void setOnActivatedListener(StatusBarNotificationPresenter presenter) {
+ mView.setOnActivatedListener(presenter);
+ }
+
+ public void setOnClickListener(View.OnClickListener onClickListener) {
+ mView.setOnClickListener(onClickListener);
+ }
+
+ public int getNotGoneIndex() {
+ return mView.getNotGoneIndex();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
index 7b2585324b9f..ff13c4e90bba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
@@ -36,7 +36,7 @@ import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.ShadeController
@@ -93,7 +93,7 @@ constructor(
private set
private val mTouchSlop: Float
private lateinit var expansionCallback: ExpansionCallback
- private lateinit var stackScroller: NotificationStackScrollLayout
+ private lateinit var stackScrollerController: NotificationStackScrollLayoutController
private val mTemp2 = IntArray(2)
private var mDraggedFarEnough: Boolean = false
private var mStartingChild: ExpandableView? = null
@@ -315,23 +315,23 @@ constructor(
private fun findView(x: Float, y: Float): ExpandableView? {
var totalX = x
var totalY = y
- stackScroller.getLocationOnScreen(mTemp2)
+ stackScrollerController.getLocationOnScreen(mTemp2)
totalX += mTemp2[0].toFloat()
totalY += mTemp2[1].toFloat()
- val childAtRawPosition = stackScroller.getChildAtRawPosition(totalX, totalY)
+ val childAtRawPosition = stackScrollerController.getChildAtRawPosition(totalX, totalY)
return if (childAtRawPosition != null && childAtRawPosition.isContentExpandable) {
childAtRawPosition
} else null
}
fun setUp(
- stackScroller: NotificationStackScrollLayout,
+ stackScrollerController: NotificationStackScrollLayoutController,
expansionCallback: ExpansionCallback,
shadeController: ShadeController
) {
this.expansionCallback = expansionCallback
this.shadeController = shadeController
- this.stackScroller = stackScroller
+ this.stackScrollerController = stackScrollerController
}
fun setPulsing(pulsing: Boolean) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java
index 7cda23544ca0..27e4adee68ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java
@@ -21,7 +21,7 @@ import android.view.LayoutInflater;
import android.view.ViewGroup;
import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
+import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent;
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.LockscreenLockIconController;
import com.android.systemui.statusbar.phone.NotificationPanelView;
@@ -41,22 +41,22 @@ public class SuperStatusBarViewFactory {
private final Context mContext;
private final InjectionInflationController mInjectionInflationController;
- private final NotificationRowComponent.Builder mNotificationRowComponentBuilder;
private final LockscreenLockIconController mLockIconController;
+ private final NotificationShelfComponent.Builder mNotificationShelfComponentBuilder;
private NotificationShadeWindowView mNotificationShadeWindowView;
private StatusBarWindowView mStatusBarWindowView;
- private NotificationShelf mNotificationShelf;
+ private NotificationShelfController mNotificationShelfController;
@Inject
public SuperStatusBarViewFactory(Context context,
InjectionInflationController injectionInflationController,
- NotificationRowComponent.Builder notificationRowComponentBuilder,
+ NotificationShelfComponent.Builder notificationShelfComponentBuilder,
LockscreenLockIconController lockIconController) {
mContext = context;
mInjectionInflationController = injectionInflationController;
- mNotificationRowComponentBuilder = notificationRowComponentBuilder;
mLockIconController = lockIconController;
+ mNotificationShelfComponentBuilder = notificationShelfComponentBuilder;
}
/**
@@ -114,25 +114,27 @@ public class SuperStatusBarViewFactory {
* 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;
+ public NotificationShelfController getNotificationShelfController(ViewGroup container) {
+ if (mNotificationShelfController != null) {
+ return mNotificationShelfController;
}
- mNotificationShelf = (NotificationShelf) mInjectionInflationController.injectable(
- LayoutInflater.from(mContext)).inflate(R.layout.status_bar_notification_shelf,
- container, /* attachToRoot= */ false);
+ NotificationShelf view = (NotificationShelf) LayoutInflater.from(mContext)
+ .inflate(R.layout.status_bar_notification_shelf, container, /* attachToRoot= */
+ false);
- NotificationRowComponent component = mNotificationRowComponentBuilder
- .activatableNotificationView(mNotificationShelf)
- .build();
- component.getActivatableNotificationViewController().init();
-
- if (mNotificationShelf == null) {
+ if (view == null) {
throw new IllegalStateException(
"R.layout.status_bar_notification_shelf could not be properly inflated");
}
- return mNotificationShelf;
+
+ NotificationShelfComponent component = mNotificationShelfComponentBuilder
+ .notificationShelf(view)
+ .build();
+ mNotificationShelfController = component.getNotificationShelfController();
+ mNotificationShelfController.init();
+
+ return mNotificationShelfController;
}
public NotificationPanelView getNotificationPanelView() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index f982cf05de97..0469176255c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -22,7 +22,7 @@ import com.android.systemui.Interpolators
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
import com.android.systemui.statusbar.phone.DozeParameters
import com.android.systemui.statusbar.phone.KeyguardBypassController
@@ -33,6 +33,7 @@ import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener
import javax.inject.Inject
import javax.inject.Singleton
+import kotlin.math.min
@Singleton
class NotificationWakeUpCoordinator @Inject constructor(
@@ -53,7 +54,7 @@ class NotificationWakeUpCoordinator @Inject constructor(
return coordinator.mLinearVisibilityAmount
}
}
- private lateinit var mStackScroller: NotificationStackScrollLayout
+ private lateinit var mStackScrollerController: NotificationStackScrollLayoutController
private var mVisibilityInterpolator = Interpolators.FAST_OUT_SLOW_IN_REVERSE
private var mLinearDozeAmount: Float = 0.0f
@@ -79,7 +80,7 @@ class NotificationWakeUpCoordinator @Inject constructor(
if (mNotificationsVisible && !mNotificationsVisibleForExpansion &&
!bypassController.bypassEnabled) {
// We're waking up while pulsing, let's make sure the animation looks nice
- mStackScroller.wakeUpFromPulse()
+ mStackScrollerController.wakeUpFromPulse()
}
if (bypassController.bypassEnabled && !mNotificationsVisible) {
// Let's make sure our huns become visible once we are waking up in case
@@ -156,10 +157,10 @@ class NotificationWakeUpCoordinator @Inject constructor(
})
}
- fun setStackScroller(stackScroller: NotificationStackScrollLayout) {
- mStackScroller = stackScroller
- pulseExpanding = stackScroller.isPulseExpanding
- stackScroller.setOnPulseHeightChangedListener {
+ fun setStackScroller(stackScrollerController: NotificationStackScrollLayoutController) {
+ mStackScrollerController = stackScrollerController
+ pulseExpanding = stackScrollerController.isPulseExpanding
+ stackScrollerController.setOnPulseHeightChangedListener {
val nowExpanding = isPulseExpanding()
val changed = nowExpanding != pulseExpanding
pulseExpanding = nowExpanding
@@ -169,7 +170,7 @@ class NotificationWakeUpCoordinator @Inject constructor(
}
}
- fun isPulseExpanding(): Boolean = mStackScroller.isPulseExpanding
+ fun isPulseExpanding(): Boolean = mStackScrollerController.isPulseExpanding
/**
* @param visible should notifications be visible
@@ -249,7 +250,7 @@ class NotificationWakeUpCoordinator @Inject constructor(
val changed = linear != mLinearDozeAmount
mLinearDozeAmount = linear
mDozeAmount = eased
- mStackScroller.setDozeAmount(mDozeAmount)
+ mStackScrollerController.setDozeAmount(mDozeAmount)
updateHideAmount()
if (changed && linear == 0.0f) {
setNotificationsVisible(visible = false, animate = false, increaseSpeed = false)
@@ -330,18 +331,18 @@ class NotificationWakeUpCoordinator @Inject constructor(
}
fun getWakeUpHeight(): Float {
- return mStackScroller.wakeUpHeight
+ return mStackScrollerController.wakeUpHeight
}
private fun updateHideAmount() {
- val linearAmount = Math.min(1.0f - mLinearVisibilityAmount, mLinearDozeAmount)
- val amount = Math.min(1.0f - mVisibilityAmount, mDozeAmount)
- mStackScroller.setHideAmount(linearAmount, amount)
+ val linearAmount = min(1.0f - mLinearVisibilityAmount, mLinearDozeAmount)
+ val amount = min(1.0f - mVisibilityAmount, mDozeAmount)
+ mStackScrollerController.setHideAmount(linearAmount, amount)
notificationsFullyHidden = linearAmount == 1.0f
}
private fun notifyAnimationStart(awake: Boolean) {
- mStackScroller.notifyHideAnimationStart(!awake)
+ mStackScrollerController.notifyHideAnimationStart(!awake)
}
override fun onDozingChanged(isDozing: Boolean) {
@@ -355,7 +356,7 @@ class NotificationWakeUpCoordinator @Inject constructor(
* from a pulse and determines how much the notifications are expanded.
*/
fun setPulseHeight(height: Float): Float {
- val overflow = mStackScroller.setPulseHeight(height)
+ val overflow = mStackScrollerController.setPulseHeight(height)
// no overflow for the bypass experience
return if (bypassController.bypassEnabled) 0.0f else overflow
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationShelfComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationShelfComponent.java
new file mode 100644
index 000000000000..af8d6ec727d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/NotificationShelfComponent.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2020 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.row.dagger;
+
+import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.NotificationShelfController;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+
+import dagger.Binds;
+import dagger.BindsInstance;
+import dagger.Module;
+import dagger.Subcomponent;
+
+/**
+ * Dagger subcomponent for NotificationShelf.
+ */
+@Subcomponent(modules = {ActivatableNotificationViewModule.class,
+ NotificationShelfComponent.NotificationShelfModule.class})
+@NotificationRowScope
+public interface NotificationShelfComponent {
+ /**
+ * Builder for {@link NotificationShelfComponent}.
+ */
+ @Subcomponent.Builder
+ interface Builder {
+ @BindsInstance
+ Builder notificationShelf(NotificationShelf view);
+ NotificationShelfComponent build();
+ }
+
+ /**
+ * Creates a NotificationShelfController.
+ */
+ @NotificationRowScope
+ NotificationShelfController getNotificationShelfController();
+ /**
+ * Dagger Module that extracts interesting properties from a NotificationShelf.
+ */
+ @Module
+ abstract class NotificationShelfModule {
+
+ /** NotificationShelf is provided as an instance of ActivatableNotificationView. */
+ @Binds
+ abstract ActivatableNotificationView bindNotificationShelf(NotificationShelf view);
+ }
+}
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 66a541a923a4..d2f8a39cc8fb 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
@@ -19,7 +19,6 @@ package com.android.systemui.statusbar.notification.stack;
import static android.service.notification.NotificationStats.DISMISSAL_SHADE;
import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
-import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
import static com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.ANCHOR_SCROLLING;
@@ -113,6 +112,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -180,8 +180,7 @@ import javax.inject.Named;
* A layout which handles a dynamic amount of notifications and presents them in a scrollable stack.
*/
public class NotificationStackScrollLayout extends ViewGroup implements ScrollAdapter,
- NotificationListContainer, ConfigurationListener, Dumpable,
- DynamicPrivacyController.Listener {
+ ConfigurationListener, Dumpable, DynamicPrivacyController.Listener {
public static final float BACKGROUND_ALPHA_DIMMED = 0.7f;
private static final String TAG = "StackScroller";
@@ -209,11 +208,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
private final Paint mBackgroundPaint = new Paint();
private final boolean mShouldDrawNotificationBackground;
private boolean mHighPriorityBeforeSpeedBump;
- private final boolean mAllowLongPress;
private boolean mDismissRtl;
private float mExpandedHeight;
private int mOwnScrollY;
+
private View mScrollAnchorView;
private int mScrollAnchorViewY;
private int mMaxLayoutHeight;
@@ -538,6 +537,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
private int mGapHeight;
private int mWaterfallTopInset;
+ private NotificationStackScrollLayoutController mController;
private SysuiColorExtractor.OnColorsChangedListener mOnColorsChangedListener =
(colorExtractor, which) -> {
@@ -545,11 +545,23 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
updateDecorViews(useDarkText);
};
+ private final ExpandableView.OnHeightChangedListener mOnChildHeightChangedListener =
+ new ExpandableView.OnHeightChangedListener() {
+ @Override
+ public void onHeightChanged(ExpandableView view, boolean needsAnimation) {
+ onChildHeightChanged(view, needsAnimation);
+ }
+
+ @Override
+ public void onReset(ExpandableView view) {
+ onChildHeightReset(view);
+ }
+ };
+
@Inject
public NotificationStackScrollLayout(
@Named(VIEW_CONTEXT) Context context,
AttributeSet attrs,
- @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress,
NotificationRoundnessManager notificationRoundnessManager,
DynamicPrivacyController dynamicPrivacyController,
SysuiStatusBarStateController statusBarStateController,
@@ -572,14 +584,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
super(context, attrs, 0, 0);
Resources res = getResources();
- mAllowLongPress = allowLongPress;
-
mRoundnessManager = notificationRoundnessManager;
mLockscreenUserManager = notificationLockscreenUserManager;
mNotificationGutsManager = notificationGutsManager;
mHeadsUpManager = headsUpManager;
- mHeadsUpManager.addListener(mRoundnessManager);
mHeadsUpManager.setAnimationStateHandler(this::setHeadsUpGoingAwayAnimationsAllowed);
mKeyguardBypassController = keyguardBypassController;
mFalsingManager = falsingManager;
@@ -611,9 +620,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
res.getBoolean(R.bool.config_drawNotificationBackground);
mFadeNotificationsOnDismiss =
res.getBoolean(R.bool.config_fadeNotificationsOnDismiss);
- mRoundnessManager.setAnimatedChildren(mChildrenToAddAnimated);
- mRoundnessManager.setOnRoundingChangedCallback(this::invalidate);
- addOnExpandedHeightChangedListener(mRoundnessManager::setExpanded);
mLockscreenUserManager.addUserChangedListener(mLockscreenUserChangeListener);
setOutlineProvider(mOutlineProvider);
@@ -640,13 +646,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
tunerService.addTunable((key, newValue) -> {
if (key.equals(HIGH_PRIORITY)) {
mHighPriorityBeforeSpeedBump = "1".equals(newValue);
- } else if (key.equals(Settings.Secure.NOTIFICATION_DISMISS_RTL)) {
- updateDismissRtlSetting("1".equals(newValue));
- } else if (key.equals(Settings.Secure.NOTIFICATION_HISTORY_ENABLED)) {
- updateFooter();
}
- }, HIGH_PRIORITY, Settings.Secure.NOTIFICATION_DISMISS_RTL,
- Settings.Secure.NOTIFICATION_HISTORY_ENABLED);
+ }, HIGH_PRIORITY);
mFeatureFlags = featureFlags;
mNotifPipeline = notifPipeline;
@@ -696,7 +697,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
}
- private void updateDismissRtlSetting(boolean dismissRtl) {
+ void updateDismissRtlSetting(boolean dismissRtl) {
mDismissRtl = dismissRtl;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
@@ -714,9 +715,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
inflateEmptyShadeView();
inflateFooterView();
mVisualStabilityManager.setVisibilityLocationProvider(this::isInVisibleLocation);
- if (mAllowLongPress) {
- setLongPressListener(mNotificationGutsManager::openGuts);
- }
}
/**
@@ -840,7 +838,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
Dependency.get(ConfigurationController.class).removeCallback(this);
}
- @Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public NotificationSwipeActionHelper getSwipeActionHelper() {
return mSwipeHelper;
@@ -1156,14 +1153,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
mNoAmbient = noAmbient;
}
- @Override
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
public void setChildLocationsChangedListener(
NotificationLogger.OnChildLocationsChangedListener listener) {
mListener = listener;
}
- @Override
+ public void setScrollAnchorView(View scrollAnchorView) {
+ mScrollAnchorView = scrollAnchorView;
+ }
+
@ShadeViewRefactor(RefactorComponent.LAYOUT_ALGORITHM)
public boolean isInVisibleLocation(NotificationEntry entry) {
ExpandableNotificationRow row = entry.getRow();
@@ -1862,7 +1861,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
}
- @Override
@ShadeViewRefactor(RefactorComponent.ADAPTER)
public ViewGroup getViewParentForNotification(NotificationEntry entry) {
return this;
@@ -2552,7 +2550,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
previous);
}
- @Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public boolean hasPulsingNotifications() {
return mPulsing;
@@ -3056,7 +3053,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
- @Override
public void cleanUpViewStateForEntry(NotificationEntry entry) {
View child = entry.getRow();
if (child == mSwipeHelper.getTranslatingParentView()) {
@@ -3323,7 +3319,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void onViewAdded(View child) {
super.onViewAdded(child);
- onViewAddedInternal((ExpandableView) child);
+ if (child instanceof ExpandableView) {
+ onViewAddedInternal((ExpandableView) child);
+ }
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
@@ -3356,9 +3354,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
- private void onViewAddedInternal(ExpandableView child) {
+ void onViewAddedInternal(ExpandableView child) {
+ child.setOnHeightChangedListener(mOnChildHeightChangedListener);
updateHideSensitiveForChild(child);
- child.setOnHeightChangedListener(this);
generateAddAnimation(child, false /* fromMoreCard */);
updateAnimationState(child);
updateChronometerForChild(child);
@@ -3380,18 +3378,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
child.setHideSensitiveForIntrinsicHeight(mAmbientState.isHideSensitive());
}
- @Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void notifyGroupChildRemoved(ExpandableView row, ViewGroup childrenContainer) {
onViewRemovedInternal(row, childrenContainer);
}
- @Override
- @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void notifyGroupChildAdded(ExpandableView row) {
- onViewAddedInternal(row);
- }
-
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
public void setAnimationsEnabled(boolean animationsEnabled) {
mAnimationsEnabled = animationsEnabled;
@@ -3416,33 +3407,29 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
- private void updateAnimationState(View child) {
+ void updateAnimationState(View child) {
updateAnimationState((mAnimationsEnabled || hasPulsingNotifications())
&& (mIsExpanded || isPinnedHeadsUp(child)), child);
}
- @Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void setExpandingNotification(ExpandableNotificationRow row) {
+ void setExpandingNotification(ExpandableNotificationRow row) {
mAmbientState.setExpandingNotification(row);
requestChildrenUpdate();
}
- @Override
@ShadeViewRefactor(RefactorComponent.ADAPTER)
- public void bindRow(ExpandableNotificationRow row) {
+ void bindRow(ExpandableNotificationRow row) {
row.setHeadsUpAnimatingAwayListener(animatingAway -> {
mRoundnessManager.onHeadsupAnimatingAwayChanged(row, animatingAway);
mHeadsUpAppearanceController.updateHeader(row.getEntry());
});
}
- @Override
public boolean containsView(View v) {
return v.getParent() == this;
}
- @Override
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
public void applyExpandAnimationParams(ExpandAnimationParameters params) {
mAmbientState.setExpandAnimationTopChange(params == null ? 0 : params.getTopChange());
@@ -3458,12 +3445,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
- public boolean isAddOrRemoveAnimationPending() {
+ boolean isAddOrRemoveAnimationPending() {
return mNeedsAnimation
&& (!mChildrenToAddAnimated.isEmpty() || !mChildrenToRemoveAnimated.isEmpty());
}
- @Override
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
public void generateAddAnimation(ExpandableView child, boolean fromMoreCard) {
if (mIsExpanded && mAnimationsEnabled && !mChangePositionInProgress && !isFullyHidden()) {
@@ -3481,7 +3467,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
}
- @Override
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
public void changeViewPosition(ExpandableView child, int newIndex) {
Assert.isMainThread();
@@ -4477,12 +4462,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
- public int getEmptyBottomMargin() {
+ int getEmptyBottomMargin() {
return Math.max(mMaxLayoutHeight - mContentHeight, 0);
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void checkSnoozeLeavebehind() {
+ void checkSnoozeLeavebehind() {
if (mCheckForLeavebehind) {
mNotificationGutsManager.closeAndSaveGuts(true /* removeLeavebehind */,
false /* force */, false /* removeControls */, -1 /* x */, -1 /* y */,
@@ -4492,19 +4477,19 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void resetCheckSnoozeLeavebehind() {
+ void resetCheckSnoozeLeavebehind() {
mCheckForLeavebehind = true;
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
- public void onExpansionStarted() {
+ void onExpansionStarted() {
mIsExpansionChanging = true;
mAmbientState.setExpansionChanging(true);
checkSnoozeLeavebehind();
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
- public void onExpansionStopped() {
+ void onExpansionStopped() {
mIsExpansionChanging = false;
resetCheckSnoozeLeavebehind();
mAmbientState.setExpansionChanging(false);
@@ -4553,20 +4538,20 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
- public void onPanelTrackingStarted() {
+ void onPanelTrackingStarted() {
mPanelTracking = true;
mAmbientState.setPanelTracking(true);
resetExposedMenuView(true /* animate */, true /* force */);
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
- public void onPanelTrackingStopped() {
+ void onPanelTrackingStopped() {
mPanelTracking = false;
mAmbientState.setPanelTracking(false);
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
- public void resetScrollPosition() {
+ void resetScrollPosition() {
mScroller.abortAnimation();
if (ANCHOR_SCROLLING) {
// TODO: once we're recycling this will need to modify the adapter position instead
@@ -4607,15 +4592,14 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
- private void updateChronometerForChild(View child) {
+ void updateChronometerForChild(View child) {
if (child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
row.setChronometerRunning(mIsExpanded);
}
}
- @Override
- public void onHeightChanged(ExpandableView view, boolean needsAnimation) {
+ void onChildHeightChanged(ExpandableView view, boolean needsAnimation) {
updateContentHeight();
updateScrollPositionOnExpandInBottom(view);
clampScrollPosition();
@@ -4638,8 +4622,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
requestChildrenUpdate();
}
- @Override
- public void onReset(ExpandableView view) {
+ void onChildHeightReset(ExpandableView view) {
updateAnimationState(view);
updateChronometerForChild(view);
}
@@ -4680,13 +4663,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void setOnHeightChangedListener(
+ void setOnHeightChangedListener(
ExpandableView.OnHeightChangedListener onHeightChangedListener) {
this.mOnHeightChangedListener = onHeightChangedListener;
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
- public void onChildAnimationFinished() {
+ void onChildAnimationFinished() {
setAnimationRunning(false);
requestChildrenUpdate();
runAnimationFinishedRunnables();
@@ -4730,7 +4713,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
* See {@link AmbientState#setDimmed}.
*/
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void setDimmed(boolean dimmed, boolean animate) {
+ void setDimmed(boolean dimmed, boolean animate) {
dimmed &= onKeyguard();
mAmbientState.setDimmed(dimmed);
if (animate && mAnimationsEnabled) {
@@ -4795,7 +4778,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
* See {@link AmbientState#setActivatedChild}.
*/
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void setActivatedChild(ActivatableNotificationView activatedChild) {
+ void setActivatedChild(ActivatableNotificationView activatedChild) {
mAmbientState.setActivatedChild(activatedChild);
if (mAnimationsEnabled) {
mActivateNeedsAnimation = true;
@@ -4871,7 +4854,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
* @param lightTheme True if light theme should be used.
*/
@ShadeViewRefactor(RefactorComponent.DECORATOR)
- public void updateDecorViews(boolean lightTheme) {
+ private void updateDecorViews(boolean lightTheme) {
if (lightTheme == mUsingLightTheme) {
return;
}
@@ -4886,7 +4869,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void goToFullShade(long delay) {
+ void goToFullShade(long delay) {
mGoToFullShadeNeedsAnimation = true;
mGoToFullShadeDelay = delay;
mNeedsAnimation = true;
@@ -4899,13 +4882,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
- public void setIntrinsicPadding(int intrinsicPadding) {
+ void setIntrinsicPadding(int intrinsicPadding) {
mIntrinsicPadding = intrinsicPadding;
mAmbientState.setIntrinsicPadding(intrinsicPadding);
}
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
- public int getIntrinsicPadding() {
+ int getIntrinsicPadding() {
return mIntrinsicPadding;
}
@@ -4939,7 +4922,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
* animation curve.
*/
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void setHideAmount(float linearHideAmount, float interpolatedHideAmount) {
+ void setHideAmount(float linearHideAmount, float interpolatedHideAmount) {
mLinearHideAmount = linearHideAmount;
mInterpolatedHideAmount = interpolatedHideAmount;
boolean wasFullyHidden = mAmbientState.isFullyHidden();
@@ -4981,7 +4964,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
- public void notifyHideAnimationStart(boolean hide) {
+ void notifyHideAnimationStart(boolean hide) {
// We only swap the scaling factor if we're fully hidden or fully awake to avoid
// interpolation issues when playing with the power button.
if (mInterpolatedHideAmount == 0 || mInterpolatedHideAmount == 1) {
@@ -5009,7 +4992,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void setFooterView(@NonNull FooterView footerView) {
+ void setFooterView(@NonNull FooterView footerView) {
int index = -1;
if (mFooterView != null) {
index = indexOfChild(mFooterView);
@@ -5020,7 +5003,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void setEmptyShadeView(EmptyShadeView emptyShadeView) {
+ void setEmptyShadeView(EmptyShadeView emptyShadeView) {
int index = -1;
if (mEmptyShadeView != null) {
index = indexOfChild(mEmptyShadeView);
@@ -5031,7 +5014,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void updateEmptyShadeView(boolean visible) {
+ void updateEmptyShadeView(boolean visible) {
mEmptyShadeView.setVisible(visible, mIsExpanded && mAnimationsEnabled);
int oldTextRes = mEmptyShadeView.getTextResource();
@@ -5215,33 +5198,28 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
}
- @Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public int getContainerChildCount() {
return getChildCount();
}
- @Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public View getContainerChildAt(int i) {
return getChildAt(i);
}
- @Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void removeContainerView(View v) {
Assert.isMainThread();
removeView(v);
}
- @Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void addContainerView(View v) {
Assert.isMainThread();
addView(v);
}
- @Override
public void addContainerViewAt(View v, int index) {
Assert.isMainThread();
addView(v, index);
@@ -5283,7 +5261,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
requestChildrenUpdate();
}
- @Override
public void setWillExpand(boolean willExpand) {
mWillExpand = willExpand;
}
@@ -5419,28 +5396,23 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void setShelf(NotificationShelf shelf) {
+ public void setShelfController(NotificationShelfController notificationShelfController) {
int index = -1;
if (mShelf != null) {
index = indexOfChild(mShelf);
removeView(mShelf);
}
- mShelf = shelf;
+ mShelf = notificationShelfController.getView();
addView(mShelf, index);
- mAmbientState.setShelf(shelf);
- mStateAnimator.setShelf(shelf);
- shelf.bind(mAmbientState, this);
+ mAmbientState.setShelf(mShelf);
+ mStateAnimator.setShelf(mShelf);
+ notificationShelfController.bind(mAmbientState, mController);
if (ANCHOR_SCROLLING) {
mScrollAnchorView = mShelf;
}
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public NotificationShelf getNotificationShelf() {
- return mShelf;
- }
-
- @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void setMaxDisplayedNotifications(int maxDisplayedNotifications) {
if (mMaxDisplayedNotifications != maxDisplayedNotifications) {
mMaxDisplayedNotifications = maxDisplayedNotifications;
@@ -5753,7 +5725,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
}
- @Override
public void setNotificationActivityStarter(
NotificationActivityStarter notificationActivityStarter) {
mNotificationActivityStarter = notificationActivityStarter;
@@ -5908,6 +5879,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
return MathUtils.smoothStep(0, totalDistance, dragDownAmount);
}
+ public void setController(
+ NotificationStackScrollLayoutController notificationStackScrollLayoutController) {
+ mController = notificationStackScrollLayoutController;
+ mController.getNoticationRoundessManager().setAnimatedChildren(mChildrenToAddAnimated);
+ }
+
+ public NotificationStackScrollLayoutController getController() {
+ return mController;
+ }
+
/**
* A listener that is notified when the empty space below the notifications is clicked on
*/
@@ -6002,7 +5983,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
}
- @Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void resetExposedMenuView(boolean animate, boolean force) {
mSwipeHelper.resetExposedMenuView(animate, force);
@@ -6754,7 +6734,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
changedRow.setChildrenExpanded(expanded, animated);
if (!mGroupExpandedForMeasure) {
- onHeightChanged(changedRow, false /* needsAnimation */);
+ onChildHeightChanged(changedRow, false /* needsAnimation */);
}
runAfterAnimationFinished(new Runnable() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
new file mode 100644
index 000000000000..e724e65e98a2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -0,0 +1,713 @@
+/*
+ * Copyright (C) 2020 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 static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+import static com.android.systemui.statusbar.phone.NotificationIconAreaController.HIGH_PRIORITY;
+
+import android.graphics.PointF;
+import android.provider.Settings;
+import android.view.Display;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowInsets;
+import android.widget.FrameLayout;
+
+import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
+import com.android.systemui.statusbar.NotificationShelfController;
+import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
+import com.android.systemui.statusbar.notification.NotificationActivityStarter;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
+import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.NotificationIconAreaController;
+import com.android.systemui.statusbar.phone.NotificationPanelViewController;
+import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
+import com.android.systemui.tuner.TunerService;
+
+import java.util.function.BiConsumer;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/**
+ * Controller for {@link NotificationStackScrollLayout}.
+ */
+@StatusBarComponent.StatusBarScope
+public class NotificationStackScrollLayoutController {
+ private final boolean mAllowLongPress;
+ private final NotificationGutsManager mNotificationGutsManager;
+ private final HeadsUpManagerPhone mHeadsUpManager;
+ private final NotificationRoundnessManager mNotificationRoundnessManager;
+ private final TunerService mTunerService;
+ private final NotificationListContainerImpl mNotificationListContainer =
+ new NotificationListContainerImpl();
+ private NotificationStackScrollLayout mView;
+
+ @Inject
+ public NotificationStackScrollLayoutController(
+ @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress,
+ NotificationGutsManager notificationGutsManager,
+ HeadsUpManagerPhone headsUpManager,
+ NotificationRoundnessManager notificationRoundnessManager,
+ TunerService tunerService) {
+ mAllowLongPress = allowLongPress;
+ mNotificationGutsManager = notificationGutsManager;
+ mHeadsUpManager = headsUpManager;
+ mNotificationRoundnessManager = notificationRoundnessManager;
+ mTunerService = tunerService;
+ }
+
+ public void attach(NotificationStackScrollLayout view) {
+ mView = view;
+ mView.setController(this);
+
+ if (mAllowLongPress) {
+ mView.setLongPressListener(mNotificationGutsManager::openGuts);
+ }
+
+ mHeadsUpManager.addListener(mNotificationRoundnessManager); // TODO: why is this here?
+
+ mNotificationRoundnessManager.setOnRoundingChangedCallback(mView::invalidate);
+ mView.addOnExpandedHeightChangedListener(mNotificationRoundnessManager::setExpanded);
+
+ mTunerService.addTunable((key, newValue) -> {
+ if (key.equals(Settings.Secure.NOTIFICATION_DISMISS_RTL)) {
+ mView.updateDismissRtlSetting("1".equals(newValue));
+ }
+ }, HIGH_PRIORITY, Settings.Secure.NOTIFICATION_DISMISS_RTL);
+ }
+
+ public void addOnExpandedHeightChangedListener(BiConsumer<Float, Float> listener) {
+ mView.addOnExpandedHeightChangedListener(listener);
+ }
+
+ public void removeOnExpandedHeightChangedListener(BiConsumer<Float, Float> listener) {
+ mView.removeOnExpandedHeightChangedListener(listener);
+ }
+
+ public void addOnLayoutChangeListener(View.OnLayoutChangeListener listener) {
+ mView.addOnLayoutChangeListener(listener);
+ }
+
+ public void removeOnLayoutChangeListener(View.OnLayoutChangeListener listener) {
+ mView.removeOnLayoutChangeListener(listener);
+ }
+
+ public void setHeadsUpAppearanceController(HeadsUpAppearanceController controller) {
+ mView.setHeadsUpAppearanceController(controller);
+ }
+
+ public void requestLayout() {
+ mView.requestLayout();
+ }
+
+ public Display getDisplay() {
+ return mView.getDisplay();
+ }
+
+ public WindowInsets getRootWindowInsets() {
+ return mView.getRootWindowInsets();
+ }
+
+ public int getRight() {
+ return mView.getRight();
+ }
+
+ public boolean isLayoutRtl() {
+ return mView.isLayoutRtl();
+ }
+
+ public float getLeft() {
+ return mView.getLeft();
+ }
+
+ public float getTranslationX() {
+ return mView.getTranslationX();
+ }
+
+ public void setOnHeightChangedListener(
+ ExpandableView.OnHeightChangedListener listener) {
+ mView.setOnHeightChangedListener(listener);
+ }
+
+ public void setOverscrollTopChangedListener(
+ NotificationStackScrollLayout.OnOverscrollTopChangedListener listener) {
+ mView.setOverscrollTopChangedListener(listener);
+ }
+
+ public void setOnEmptySpaceClickListener(
+ NotificationStackScrollLayout.OnEmptySpaceClickListener listener) {
+ mView.setOnEmptySpaceClickListener(listener);
+ }
+
+ public void setTrackingHeadsUp(ExpandableNotificationRow expandableNotificationRow) {
+ mView.setTrackingHeadsUp(expandableNotificationRow);
+ }
+
+ public void wakeUpFromPulse() {
+ mView.wakeUpFromPulse();
+ }
+
+ public boolean isPulseExpanding() {
+ return mView.isPulseExpanding();
+ }
+
+ public void setOnPulseHeightChangedListener(Runnable listener) {
+ mView.setOnPulseHeightChangedListener(listener);
+ }
+
+ public void setDozeAmount(float amount) {
+ mView.setDozeAmount(amount);
+ }
+
+ public float getWakeUpHeight() {
+ return mView.getWakeUpHeight();
+ }
+
+ public void setHideAmount(float linearAmount, float amount) {
+ mView.setHideAmount(linearAmount, amount);
+ }
+
+ public void notifyHideAnimationStart(boolean hide) {
+ mView.notifyHideAnimationStart(hide);
+ }
+
+ public float setPulseHeight(float height) {
+ return mView.setPulseHeight(height);
+ }
+
+ public void getLocationOnScreen(int[] outLocation) {
+ mView.getLocationOnScreen(outLocation);
+ }
+
+ public ExpandableView getChildAtRawPosition(float x, float y) {
+ return mView.getChildAtRawPosition(x, y);
+ }
+
+ public FrameLayout.LayoutParams getLayoutParams() {
+ return (FrameLayout.LayoutParams) mView.getLayoutParams();
+ }
+
+ public void setLayoutParams(FrameLayout.LayoutParams lp) {
+ mView.setLayoutParams(lp);
+ }
+
+ public void setIsFullWidth(boolean isFullWidth) {
+ mView.setIsFullWidth(isFullWidth);
+ }
+
+ public boolean isAddOrRemoveAnimationPending() {
+ return mView.isAddOrRemoveAnimationPending();
+ }
+
+ public int getVisibleNotificationCount() {
+ return mView.getVisibleNotificationCount();
+ }
+
+ public int getIntrinsicContentHeight() {
+ return mView.getIntrinsicContentHeight();
+ }
+
+ public void setIntrinsicPadding(int intrinsicPadding) {
+ mView.setIntrinsicPadding(intrinsicPadding);
+ }
+
+ public int getHeight() {
+ return mView.getHeight();
+ }
+
+ public int getChildCount() {
+ return mView.getChildCount();
+ }
+
+ public ExpandableView getChildAt(int i) {
+ return (ExpandableView) mView.getChildAt(i);
+ }
+
+ public void goToFullShade(long delay) {
+ mView.goToFullShade(delay);
+ }
+
+ public void setOverScrollAmount(float amount, boolean onTop, boolean animate,
+ boolean cancelAnimators) {
+ mView.setOverScrollAmount(amount, onTop, animate, cancelAnimators);
+ }
+
+ public void setOverScrollAmount(float amount, boolean onTop, boolean animate) {
+ mView.setOverScrollAmount(amount, onTop, animate);
+ }
+
+ public void setOverScrolledPixels(float numPixels, boolean onTop, boolean animate) {
+ mView.setOverScrolledPixels(numPixels, onTop, animate);
+ }
+
+ public void resetScrollPosition() {
+ mView.resetScrollPosition();
+ }
+
+ public void setShouldShowShelfOnly(boolean shouldShowShelfOnly) {
+ mView.setShouldShowShelfOnly(shouldShowShelfOnly);
+ }
+
+ public void cancelLongPress() {
+ mView.cancelLongPress();
+ }
+
+ public float getX() {
+ return mView.getX();
+ }
+
+ public boolean isBelowLastNotification(float x, float y) {
+ return mView.isBelowLastNotification(x, y);
+ }
+
+ public float getWidth() {
+ return mView.getWidth();
+ }
+
+ public float getOpeningHeight() {
+ return mView.getOpeningHeight();
+ }
+
+ public float getBottomMostNotificationBottom() {
+ return mView.getBottomMostNotificationBottom();
+ }
+
+ public void checkSnoozeLeavebehind() {
+ mView.checkSnoozeLeavebehind();
+ }
+
+ public void setQsExpanded(boolean expanded) {
+ mView.setQsExpanded(expanded);
+ }
+
+ public void setScrollingEnabled(boolean enabled) {
+ mView.setScrollingEnabled(enabled);
+ }
+
+ public void setQsExpansionFraction(float expansionFraction) {
+ mView.setQsExpansionFraction(expansionFraction);
+ }
+
+ public float calculateAppearFractionBypass() {
+ return mView.calculateAppearFractionBypass();
+ }
+
+ public void updateTopPadding(float qsHeight, boolean animate) {
+ mView.updateTopPadding(qsHeight, animate);
+ }
+
+ public void resetCheckSnoozeLeavebehind() {
+ mView.resetCheckSnoozeLeavebehind();
+ }
+
+ public boolean isScrolledToBottom() {
+ return mView.isScrolledToBottom();
+ }
+
+ public int getNotGoneChildCount() {
+ return mView.getNotGoneChildCount();
+ }
+
+ public float getIntrinsicPadding() {
+ return mView.getIntrinsicPadding();
+ }
+
+ public float getLayoutMinHeight() {
+ return mView.getLayoutMinHeight();
+ }
+
+ public int getEmptyBottomMargin() {
+ return mView.getEmptyBottomMargin();
+ }
+
+ public float getTopPaddingOverflow() {
+ return mView.getTopPaddingOverflow();
+ }
+
+ public int getTopPadding() {
+ return mView.getTopPadding();
+ }
+
+ public float getEmptyShadeViewHeight() {
+ return mView.getEmptyShadeViewHeight();
+ }
+
+ public void setAlpha(float alpha) {
+ mView.setAlpha(alpha);
+ }
+
+ public float getCurrentOverScrollAmount(boolean top) {
+ return mView.getCurrentOverScrollAmount(top);
+ }
+
+ public float getCurrentOverScrolledPixels(boolean top) {
+ return mView.getCurrentOverScrolledPixels(top);
+ }
+
+ public float calculateAppearFraction(float height) {
+ return mView.calculateAppearFraction(height);
+ }
+
+ public void onExpansionStarted() {
+ mView.onExpansionStarted();
+ }
+
+ public void onExpansionStopped() {
+ mView.onExpansionStopped();
+ }
+
+ public void onPanelTrackingStarted() {
+ mView.onPanelTrackingStarted();
+ }
+
+ public void onPanelTrackingStopped() {
+ mView.onPanelTrackingStopped();
+ }
+
+ public void setHeadsUpBoundaries(int height, int bottomBarHeight) {
+ mView.setHeadsUpBoundaries(height, bottomBarHeight);
+ }
+
+ public void setUnlockHintRunning(boolean running) {
+ mView.setUnlockHintRunning(running);
+ }
+
+ public float getPeekHeight() {
+ return mView.getPeekHeight();
+ }
+
+ public boolean isFooterViewNotGone() {
+ return mView.isFooterViewNotGone();
+ }
+
+ public boolean isFooterViewContentVisible() {
+ return mView.isFooterViewContentVisible();
+ }
+
+ public int getFooterViewHeightWithPadding() {
+ return mView.getFooterViewHeightWithPadding();
+ }
+
+ public void updateEmptyShadeView(boolean visible) {
+ mView.updateEmptyShadeView(visible);
+ }
+
+ public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
+ mView.setHeadsUpAnimatingAway(headsUpAnimatingAway);
+ }
+
+ public HeadsUpTouchHelper.Callback getHeadsUpCallback() {
+ return mView.getHeadsUpCallback();
+ }
+
+ public void forceNoOverlappingRendering(boolean force) {
+ mView.forceNoOverlappingRendering(force);
+ }
+
+ public void setTranslationX(float translation) {
+ mView.setTranslationX(translation);
+ }
+
+ public void setExpandingVelocity(float velocity) {
+ mView.setExpandingVelocity(velocity);
+ }
+
+ public void setExpandedHeight(float expandedHeight) {
+ mView.setExpandedHeight(expandedHeight);
+ }
+
+ public void setQsContainer(ViewGroup view) {
+ mView.setQsContainer(view);
+ }
+
+ public void setAnimationsEnabled(boolean enabled) {
+ mView.setAnimationsEnabled(enabled);
+ }
+
+ public void setDozing(boolean dozing, boolean animate, PointF wakeUpTouchLocation) {
+ mView.setDozing(dozing, animate, wakeUpTouchLocation);
+ }
+
+ public void setPulsing(boolean pulsing, boolean animatePulse) {
+ mView.setPulsing(pulsing, animatePulse);
+ }
+
+ public boolean hasActiveClearableNotifications(
+ @NotificationStackScrollLayout.SelectedRows int selection) {
+ return mView.hasActiveClearableNotifications(selection);
+ }
+
+ public RemoteInputController.Delegate createDelegate() {
+ return mView.createDelegate();
+ }
+
+ public void updateSectionBoundaries(String reason) {
+ mView.updateSectionBoundaries(reason);
+ }
+
+ public void updateSpeedBumpIndex() {
+ mView.updateSpeedBumpIndex();
+ }
+
+ public void updateFooter() {
+ mView.updateFooter();
+ }
+
+ public void updateIconAreaViews() {
+ mView.updateIconAreaViews();
+ }
+
+ public void onUpdateRowStates() {
+ mView.onUpdateRowStates();
+ }
+
+ public ActivatableNotificationView getActivatedChild() {
+ return mView.getActivatedChild();
+ }
+
+ public void setActivatedChild(ActivatableNotificationView view) {
+ mView.setActivatedChild(view);
+ }
+
+ public void runAfterAnimationFinished(Runnable r) {
+ mView.runAfterAnimationFinished(r);
+ }
+
+ public void setNotificationPanelController(
+ NotificationPanelViewController notificationPanelViewController) {
+ mView.setNotificationPanelController(notificationPanelViewController);
+ }
+
+ public void setIconAreaController(NotificationIconAreaController controller) {
+ mView.setIconAreaController(controller);
+ }
+
+ public void setStatusBar(StatusBar statusBar) {
+ mView.setStatusBar(statusBar);
+ }
+
+ public void setGroupManager(NotificationGroupManager groupManager) {
+ mView.setGroupManager(groupManager);
+ }
+
+ public void setShelfController(NotificationShelfController notificationShelfController) {
+ mView.setShelfController(notificationShelfController);
+ }
+
+ public void setScrimController(ScrimController scrimController) {
+ mView.setScrimController(scrimController);
+ }
+
+ public ExpandableView getFirstChildNotGone() {
+ return mView.getFirstChildNotGone();
+ }
+
+ public void setInHeadsUpPinnedMode(boolean inPinnedMode) {
+ mView.setInHeadsUpPinnedMode(inPinnedMode);
+ }
+
+ public void generateHeadsUpAnimation(NotificationEntry entry, boolean isHeadsUp) {
+ mView.generateHeadsUpAnimation(entry, isHeadsUp);
+ }
+
+ public void generateHeadsUpAnimation(ExpandableNotificationRow row, boolean isHeadsUp) {
+ mView.generateHeadsUpAnimation(row, isHeadsUp);
+ }
+
+ public void setMaxTopPadding(int padding) {
+ mView.setMaxTopPadding(padding);
+ }
+
+ public int getTransientViewCount() {
+ return mView.getTransientViewCount();
+ }
+
+ public View getTransientView(int i) {
+ return mView.getTransientView(i);
+ }
+
+ public int getPositionInLinearLayout(ExpandableView row) {
+ return mView.getPositionInLinearLayout(row);
+ }
+
+ public NotificationStackScrollLayout getView() {
+ return mView;
+ }
+
+ public float calculateGapHeight(ExpandableView previousView, ExpandableView child, int count) {
+ return mView.calculateGapHeight(previousView, child, count);
+ }
+
+ public NotificationRoundnessManager getNoticationRoundessManager() {
+ return mNotificationRoundnessManager;
+ }
+
+ public NotificationListContainer getNotificationListContainer() {
+ return mNotificationListContainer;
+ }
+
+ private class NotificationListContainerImpl implements NotificationListContainer {
+ @Override
+ public void setChildTransferInProgress(boolean childTransferInProgress) {
+ mView.setChildTransferInProgress(childTransferInProgress);
+ }
+
+ @Override
+ public void changeViewPosition(ExpandableView child, int newIndex) {
+ mView.changeViewPosition(child, newIndex);
+ }
+
+ @Override
+ public void notifyGroupChildAdded(ExpandableView row) {
+ mView.onViewAddedInternal(row);
+ }
+
+ @Override
+ public void notifyGroupChildRemoved(ExpandableView row, ViewGroup childrenContainer) {
+ mView.notifyGroupChildRemoved(row, childrenContainer);
+ }
+
+ @Override
+ public void generateAddAnimation(ExpandableView child, boolean fromMoreCard) {
+ mView.generateAddAnimation(child, fromMoreCard);
+ }
+
+ @Override
+ public void generateChildOrderChangedEvent() {
+ mView.generateChildOrderChangedEvent();
+ }
+
+ @Override
+ public int getContainerChildCount() {
+ return mView.getContainerChildCount();
+ }
+
+ @Override
+ public void setNotificationActivityStarter(
+ NotificationActivityStarter notificationActivityStarter) {
+ mView.setNotificationActivityStarter(notificationActivityStarter);
+ }
+
+ @Override
+ public View getContainerChildAt(int i) {
+ return mView.getContainerChildAt(i);
+ }
+
+ @Override
+ public void removeContainerView(View v) {
+ mView.removeContainerView(v);
+ }
+
+ @Override
+ public void addContainerView(View v) {
+ mView.addContainerView(v);
+ }
+
+ @Override
+ public void addContainerViewAt(View v, int index) {
+ mView.addContainerViewAt(v, index);
+ }
+
+ @Override
+ public void setMaxDisplayedNotifications(int maxNotifications) {
+ mView.setMaxDisplayedNotifications(maxNotifications);
+ }
+
+ @Override
+ public ViewGroup getViewParentForNotification(NotificationEntry entry) {
+ return mView.getViewParentForNotification(entry);
+ }
+
+ @Override
+ public void resetExposedMenuView(boolean animate, boolean force) {
+ mView.resetExposedMenuView(animate, force);
+ }
+
+ @Override
+ public NotificationSwipeActionHelper getSwipeActionHelper() {
+ return mView.getSwipeActionHelper();
+ }
+
+ @Override
+ public void cleanUpViewStateForEntry(NotificationEntry entry) {
+ mView.cleanUpViewStateForEntry(entry);
+ }
+
+ @Override
+ public void setChildLocationsChangedListener(
+ NotificationLogger.OnChildLocationsChangedListener listener) {
+
+ }
+
+ public boolean hasPulsingNotifications() {
+ return mView.hasPulsingNotifications();
+ }
+
+ @Override
+ public boolean isInVisibleLocation(NotificationEntry entry) {
+ return mView.isInVisibleLocation(entry);
+ }
+
+ @Override
+ public void onHeightChanged(ExpandableView view, boolean needsAnimation) {
+ mView.onChildHeightChanged(view, needsAnimation);
+ }
+
+ @Override
+ public void onReset(ExpandableView view) {
+ mView.onChildHeightReset(view);
+ }
+
+ @Override
+ public void bindRow(ExpandableNotificationRow row) {
+ mView.bindRow(row);
+ }
+
+ @Override
+ public void applyExpandAnimationParams(
+ ActivityLaunchAnimator.ExpandAnimationParameters params) {
+ mView.applyExpandAnimationParams(params);
+ }
+
+ @Override
+ public void setExpandingNotification(ExpandableNotificationRow row) {
+ mView.setExpandingNotification(row);
+ }
+
+ @Override
+ public boolean containsView(View v) {
+ return mView.containsView(v);
+ }
+
+ @Override
+ public void setWillExpand(boolean willExpand) {
+ mView.setWillExpand(willExpand);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index 51c02c9f93ab..8cdaa63994e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -36,7 +36,7 @@ import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
@@ -52,7 +52,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
public static final int CONTENT_FADE_DELAY = 100;
private final NotificationIconAreaController mNotificationIconAreaController;
private final HeadsUpManagerPhone mHeadsUpManager;
- private final NotificationStackScrollLayout mStackScroller;
+ private final NotificationStackScrollLayoutController mStackScrollerController;
private final HeadsUpStatusBarView mHeadsUpStatusBarView;
private final View mCenteredIconView;
private final View mClockView;
@@ -93,7 +93,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
public HeadsUpAppearanceController(
NotificationIconAreaController notificationIconAreaController,
HeadsUpManagerPhone headsUpManager,
- View notificationShadeView,
+ NotificationStackScrollLayoutController notificationStackScrollLayoutController,
SysuiStatusBarStateController statusBarStateController,
KeyguardBypassController keyguardBypassController,
KeyguardStateController keyguardStateController,
@@ -101,10 +101,9 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
NotificationPanelViewController notificationPanelViewController, View statusBarView) {
this(notificationIconAreaController, headsUpManager, statusBarStateController,
keyguardBypassController, wakeUpCoordinator, keyguardStateController,
- commandQueue,
- statusBarView.findViewById(R.id.heads_up_status_bar_view),
- notificationShadeView.findViewById(R.id.notification_stack_scroller),
+ commandQueue, notificationStackScrollLayoutController,
notificationPanelViewController,
+ statusBarView.findViewById(R.id.heads_up_status_bar_view),
statusBarView.findViewById(R.id.clock),
statusBarView.findViewById(R.id.operator_name_frame),
statusBarView.findViewById(R.id.centered_icon_area));
@@ -119,9 +118,9 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
NotificationWakeUpCoordinator wakeUpCoordinator,
KeyguardStateController keyguardStateController,
CommandQueue commandQueue,
- HeadsUpStatusBarView headsUpStatusBarView,
- NotificationStackScrollLayout stackScroller,
+ NotificationStackScrollLayoutController stackScrollerController,
NotificationPanelViewController notificationPanelViewController,
+ HeadsUpStatusBarView headsUpStatusBarView,
View clockView,
View operatorNameView,
View centeredIconView) {
@@ -132,14 +131,14 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
mCenteredIconView = centeredIconView;
headsUpStatusBarView.setOnDrawingRectChangedListener(
() -> updateIsolatedIconLocation(true /* requireUpdate */));
- mStackScroller = stackScroller;
+ mStackScrollerController = stackScrollerController;
mNotificationPanelViewController = notificationPanelViewController;
notificationPanelViewController.addTrackingHeadsUpListener(mSetTrackingHeadsUp);
notificationPanelViewController.addVerticalTranslationListener(mUpdatePanelTranslation);
notificationPanelViewController.setHeadsUpAppearanceController(this);
- mStackScroller.addOnExpandedHeightChangedListener(mSetExpandedHeight);
- mStackScroller.addOnLayoutChangeListener(mStackScrollLayoutChangeListener);
- mStackScroller.setHeadsUpAppearanceController(this);
+ mStackScrollerController.addOnExpandedHeightChangedListener(mSetExpandedHeight);
+ mStackScrollerController.addOnLayoutChangeListener(mStackScrollLayoutChangeListener);
+ mStackScrollerController.setHeadsUpAppearanceController(this);
mClockView = clockView;
mOperatorNameView = operatorNameView;
mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
@@ -153,7 +152,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
updateTopEntry();
// trigger scroller to notify the latest panel translation
- mStackScroller.requestLayout();
+ mStackScrollerController.requestLayout();
}
mHeadsUpStatusBarView.removeOnLayoutChangeListener(this);
}
@@ -174,8 +173,8 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
mNotificationPanelViewController.removeTrackingHeadsUpListener(mSetTrackingHeadsUp);
mNotificationPanelViewController.removeVerticalTranslationListener(mUpdatePanelTranslation);
mNotificationPanelViewController.setHeadsUpAppearanceController(null);
- mStackScroller.removeOnExpandedHeightChangedListener(mSetExpandedHeight);
- mStackScroller.removeOnLayoutChangeListener(mStackScrollLayoutChangeListener);
+ mStackScrollerController.removeOnExpandedHeightChangedListener(mSetExpandedHeight);
+ mStackScrollerController.removeOnLayoutChangeListener(mStackScrollLayoutChangeListener);
mDarkIconDispatcher.removeDarkReceiver(this);
}
@@ -219,12 +218,12 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
}
int realDisplaySize = 0;
- if (mStackScroller.getDisplay() != null) {
- mStackScroller.getDisplay().getRealSize(mPoint);
+ if (mStackScrollerController.getDisplay() != null) {
+ mStackScrollerController.getDisplay().getRealSize(mPoint);
realDisplaySize = mPoint.x;
}
- WindowInsets windowInset = mStackScroller.getRootWindowInsets();
+ WindowInsets windowInset = mStackScrollerController.getRootWindowInsets();
DisplayCutout cutout = (windowInset != null) ? windowInset.getDisplayCutout() : null;
int sysWinLeft = (windowInset != null) ? windowInset.getStableInsetLeft() : 0;
int sysWinRight = (windowInset != null) ? windowInset.getStableInsetRight() : 0;
@@ -233,17 +232,17 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
int leftInset = Math.max(sysWinLeft, cutoutLeft);
int rightInset = Math.max(sysWinRight, cutoutRight);
- return leftInset + mStackScroller.getRight() + rightInset - realDisplaySize;
+ return leftInset + mStackScrollerController.getRight() + rightInset - realDisplaySize;
}
public void updatePanelTranslation() {
float newTranslation;
- if (mStackScroller.isLayoutRtl()) {
+ if (mStackScrollerController.isLayoutRtl()) {
newTranslation = getRtlTranslation();
} else {
- newTranslation = mStackScroller.getLeft();
+ newTranslation = mStackScrollerController.getLeft();
}
- newTranslation += mStackScroller.getTranslationX();
+ newTranslation += mStackScrollerController.getTranslationX();
mHeadsUpStatusBarView.setPanelTranslation(newTranslation);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 9d3e915cad69..7bbe1c986249 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -26,7 +26,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.NotificationUtils;
@@ -160,9 +160,9 @@ public class NotificationIconAreaController implements DarkReceiver,
}
}
- public void setupShelf(NotificationShelf shelf) {
- mShelfIcons = shelf.getShelfIcons();
- shelf.setCollapsedIcons(mNotificationIcons);
+ public void setupShelf(NotificationShelfController notificationShelfController) {
+ mShelfIcons = notificationShelfController.getShelfIcons();
+ notificationShelfController.setCollapsedIcons(mNotificationIcons);
}
public void onDensityOrFontScaleChanged(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index a87311a69ab5..42fbe5967d42 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -86,6 +86,7 @@ import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
@@ -105,6 +106,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
@@ -174,6 +176,7 @@ public class NotificationPanelViewController extends PanelViewController {
private final ZenModeController mZenModeController;
private final ConfigurationController mConfigurationController;
private final FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder;
+ private final NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
// Cap and total height of Roboto font. Needs to be adjusted when font for the big clock is
// changed.
@@ -264,7 +267,6 @@ public class NotificationPanelViewController extends PanelViewController {
private KeyguardStatusView mKeyguardStatusView;
private View mQsNavbarScrim;
private NotificationsQuickSettingsContainer mNotificationContainerParent;
- private NotificationStackScrollLayout mNotificationStackScroller;
private boolean mAnimateNextPositionUpdate;
private int mTrackingPointer;
@@ -454,6 +456,7 @@ public class NotificationPanelViewController extends PanelViewController {
private boolean mAnimatingQS;
private int mOldLayoutDirection;
+ private NotificationShelfController mNotificationShelfController;
private View.AccessibilityDelegate mAccessibilityDelegate = new View.AccessibilityDelegate() {
@Override
@@ -498,7 +501,8 @@ public class NotificationPanelViewController extends PanelViewController {
MediaHierarchyManager mediaHierarchyManager,
BiometricUnlockController biometricUnlockController,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
- Provider<KeyguardClockSwitchController> keyguardClockSwitchControllerProvider) {
+ Provider<KeyguardClockSwitchController> keyguardClockSwitchControllerProvider,
+ NotificationStackScrollLayoutController notificationStackScrollLayoutController) {
super(view, falsingManager, dozeLog, keyguardStateController,
(SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
latencyTracker, flingAnimationUtilsBuilder, statusBarTouchableRegionManager);
@@ -511,6 +515,7 @@ public class NotificationPanelViewController extends PanelViewController {
mMediaHierarchyManager = mediaHierarchyManager;
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mKeyguardClockSwitchControllerProvider = keyguardClockSwitchControllerProvider;
+ mNotificationStackScrollLayoutController = notificationStackScrollLayoutController;
mView.setWillNotDraw(!DEBUG);
mInjectionInflationController = injectionInflationController;
mFalsingManager = falsingManager;
@@ -590,21 +595,26 @@ public class NotificationPanelViewController extends PanelViewController {
keyguardClockSwitchController.setBigClockContainer(mBigClockContainer);
mNotificationContainerParent = mView.findViewById(R.id.notification_container_parent);
- mNotificationStackScroller = mView.findViewById(R.id.notification_stack_scroller);
- mNotificationStackScroller.setOnHeightChangedListener(mOnHeightChangedListener);
- mNotificationStackScroller.setOverscrollTopChangedListener(mOnOverscrollTopChangedListener);
- mNotificationStackScroller.setOnEmptySpaceClickListener(mOnEmptySpaceClickListener);
- addTrackingHeadsUpListener(mNotificationStackScroller::setTrackingHeadsUp);
+ NotificationStackScrollLayout stackScrollLayout = mView.findViewById(
+ R.id.notification_stack_scroller);
+ mNotificationStackScrollLayoutController.attach(stackScrollLayout);
+ mNotificationStackScrollLayoutController.setOnHeightChangedListener(
+ mOnHeightChangedListener);
+ mNotificationStackScrollLayoutController.setOverscrollTopChangedListener(
+ mOnOverscrollTopChangedListener);
+ mNotificationStackScrollLayoutController.setOnEmptySpaceClickListener(
+ mOnEmptySpaceClickListener);
+ addTrackingHeadsUpListener(mNotificationStackScrollLayoutController::setTrackingHeadsUp);
mKeyguardBottomArea = mView.findViewById(R.id.keyguard_bottom_area);
mQsNavbarScrim = mView.findViewById(R.id.qs_navbar_scrim);
mLastOrientation = mResources.getConfiguration().orientation;
initBottomArea();
- mWakeUpCoordinator.setStackScroller(mNotificationStackScroller);
+ mWakeUpCoordinator.setStackScroller(mNotificationStackScrollLayoutController);
mQsFrame = mView.findViewById(R.id.qs_frame);
mPulseExpansionHandler.setUp(
- mNotificationStackScroller, mExpansionCallback, mShadeController);
+ mNotificationStackScrollLayoutController, mExpansionCallback, mShadeController);
mWakeUpCoordinator.addListener(new NotificationWakeUpCoordinator.WakeUpListener() {
@Override
public void onFullyHiddenChanged(boolean isFullyHidden) {
@@ -688,11 +698,11 @@ public class NotificationPanelViewController extends PanelViewController {
}
int panelWidth = mResources.getDimensionPixelSize(R.dimen.notification_panel_width);
- lp = (FrameLayout.LayoutParams) mNotificationStackScroller.getLayoutParams();
+ lp = mNotificationStackScrollLayoutController.getLayoutParams();
if (lp.width != panelWidth || lp.gravity != panelGravity) {
lp.width = panelWidth;
lp.gravity = panelGravity;
- mNotificationStackScroller.setLayoutParams(lp);
+ mNotificationStackScrollLayoutController.setLayoutParams(lp);
}
}
@@ -770,7 +780,7 @@ public class NotificationPanelViewController extends PanelViewController {
private void setIsFullWidth(boolean isFullWidth) {
mIsFullWidth = isFullWidth;
- mNotificationStackScroller.setIsFullWidth(isFullWidth);
+ mNotificationStackScrollLayoutController.setIsFullWidth(isFullWidth);
}
private void startQsSizeChangeAnimation(int oldHeight, final int newHeight) {
@@ -804,7 +814,7 @@ public class NotificationPanelViewController extends PanelViewController {
* showing.
*/
private void positionClockAndNotifications() {
- boolean animate = mNotificationStackScroller.isAddOrRemoveAnimationPending();
+ boolean animate = mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending();
boolean animateClock = animate || mAnimateNextPositionUpdate;
int stackScrollerPadding;
if (mBarState != StatusBarState.KEYGUARD) {
@@ -814,12 +824,12 @@ public class NotificationPanelViewController extends PanelViewController {
int bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding);
int clockPreferredY = mKeyguardStatusView.getClockPreferredY(totalHeight);
boolean bypassEnabled = mKeyguardBypassController.getBypassEnabled();
- final boolean
- hasVisibleNotifications =
- !bypassEnabled && mNotificationStackScroller.getVisibleNotificationCount() != 0;
+ final boolean hasVisibleNotifications = !bypassEnabled
+ && mNotificationStackScrollLayoutController.getVisibleNotificationCount() != 0;
mKeyguardStatusView.setHasVisibleNotifications(hasVisibleNotifications);
mClockPositionAlgorithm.setup(mStatusBarMinHeight, totalHeight - bottomPadding,
- mNotificationStackScroller.getIntrinsicContentHeight(), getExpandedFraction(),
+ mNotificationStackScrollLayoutController.getIntrinsicContentHeight(),
+ getExpandedFraction(),
totalHeight, (int) (mKeyguardStatusView.getHeight() - mShelfHeight / 2.0f
- mDarkIconSize / 2.0f), clockPreferredY, hasCustomClock(),
hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount,
@@ -833,7 +843,7 @@ public class NotificationPanelViewController extends PanelViewController {
updateClock();
stackScrollerPadding = mClockPositionResult.stackScrollerPaddingExpanded;
}
- mNotificationStackScroller.setIntrinsicPadding(stackScrollerPadding);
+ mNotificationStackScrollLayoutController.setIntrinsicPadding(stackScrollerPadding);
mKeyguardBottomArea.setAntiBurnInOffsetX(mClockPositionResult.clockX);
mStackScrollerMeasuringPass++;
@@ -858,36 +868,51 @@ public class NotificationPanelViewController extends PanelViewController {
float minPadding = mClockPositionAlgorithm.getMinStackScrollerPadding();
int notificationPadding = Math.max(
1, mResources.getDimensionPixelSize(R.dimen.notification_divider_height));
- NotificationShelf shelf = mNotificationStackScroller.getNotificationShelf();
+ NotificationShelf shelf = mNotificationShelfController.getView();
float
shelfSize =
shelf.getVisibility() == View.GONE ? 0
: shelf.getIntrinsicHeight() + notificationPadding;
float
availableSpace =
- mNotificationStackScroller.getHeight() - minPadding - shelfSize - Math.max(
- mIndicationBottomPadding, mAmbientIndicationBottomPadding)
+ mNotificationStackScrollLayoutController.getHeight() - minPadding - shelfSize
+ - Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding)
- mKeyguardStatusView.getLogoutButtonHeight();
int count = 0;
ExpandableView previousView = null;
- for (int i = 0; i < mNotificationStackScroller.getChildCount(); i++) {
- ExpandableView child = (ExpandableView) mNotificationStackScroller.getChildAt(i);
+ for (int i = 0; i < mNotificationStackScrollLayoutController.getChildCount(); i++) {
+ ExpandableView child = mNotificationStackScrollLayoutController.getChildAt(i);
+ if (!(child instanceof ExpandableNotificationRow)) {
+ continue;
+ }
+ ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ boolean
+ suppressedSummary =
+ mGroupManager != null && mGroupManager.isSummaryOfSuppressedGroup(
+ row.getEntry().getSbn());
+ if (suppressedSummary) {
+ continue;
+ }
if (!canShowViewOnLockscreen(child)) {
continue;
}
+ if (row.isRemoved()) {
+ continue;
+ }
availableSpace -= child.getMinHeight(true /* ignoreTemporaryStates */);
availableSpace -= count == 0 ? 0 : notificationPadding;
- availableSpace -= mNotificationStackScroller.calculateGapHeight(previousView, child,
- count);
+ availableSpace -= mNotificationStackScrollLayoutController
+ .calculateGapHeight(previousView, child, count);
previousView = child;
if (availableSpace >= 0 && count < maximum) {
count++;
} else if (availableSpace > -shelfSize) {
// if we are exactly the last view, then we can show us still!
- for (int j = i + 1; j < mNotificationStackScroller.getChildCount(); j++) {
- ExpandableView view = (ExpandableView) mNotificationStackScroller.getChildAt(j);
- if (view instanceof ExpandableNotificationRow &&
- canShowViewOnLockscreen(view)) {
+ int childCount = mNotificationStackScrollLayoutController.getChildCount();
+ for (int j = i + 1; j < childCount; j++) {
+ ExpandableView view = mNotificationStackScrollLayoutController.getChildAt(j);
+ if (view instanceof ExpandableNotificationRow
+ && canShowViewOnLockscreen(view)) {
return count;
}
}
@@ -952,7 +977,7 @@ public class NotificationPanelViewController extends PanelViewController {
}
public void animateToFullShade(long delay) {
- mNotificationStackScroller.goToFullShade(delay);
+ mNotificationStackScrollLayoutController.goToFullShade(delay);
mView.requestLayout();
mAnimateNextPositionUpdate = true;
}
@@ -978,9 +1003,9 @@ public class NotificationPanelViewController extends PanelViewController {
} else {
closeQs();
}
- mNotificationStackScroller.setOverScrollAmount(0f, true /* onTop */, animate,
+ mNotificationStackScrollLayoutController.setOverScrollAmount(0f, true /* onTop */, animate,
!animate /* cancelAnimators */);
- mNotificationStackScroller.resetScrollPosition();
+ mNotificationStackScrollLayoutController.resetScrollPosition();
}
@Override
@@ -991,7 +1016,7 @@ public class NotificationPanelViewController extends PanelViewController {
if (mQsExpanded) {
mQsExpandImmediate = true;
- mNotificationStackScroller.setShouldShowShelfOnly(true);
+ mNotificationStackScrollLayoutController.setShouldShowShelfOnly(true);
}
super.collapse(delayed, speedUpFactor);
}
@@ -1027,7 +1052,7 @@ public class NotificationPanelViewController extends PanelViewController {
public void expandWithQs() {
if (mQsExpansionEnabled) {
mQsExpandImmediate = true;
- mNotificationStackScroller.setShouldShowShelfOnly(true);
+ mNotificationStackScrollLayoutController.setShouldShowShelfOnly(true);
}
if (isFullyCollapsed()) {
expand(true /* animate */);
@@ -1088,7 +1113,7 @@ public class NotificationPanelViewController extends PanelViewController {
onQsExpansionStarted();
mInitialHeightOnTouch = mQsExpansionHeight;
mQsTracking = true;
- mNotificationStackScroller.cancelLongPress();
+ mNotificationStackScrollLayoutController.cancelLongPress();
}
break;
case MotionEvent.ACTION_POINTER_UP:
@@ -1124,7 +1149,7 @@ public class NotificationPanelViewController extends PanelViewController {
mInitialHeightOnTouch = mQsExpansionHeight;
mInitialTouchY = y;
mInitialTouchX = x;
- mNotificationStackScroller.cancelLongPress();
+ mNotificationStackScrollLayoutController.cancelLongPress();
return true;
}
break;
@@ -1144,9 +1169,11 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
protected boolean isInContentBounds(float x, float y) {
- float stackScrollerX = mNotificationStackScroller.getX();
- return !mNotificationStackScroller.isBelowLastNotification(x - stackScrollerX, y)
- && stackScrollerX < x && x < stackScrollerX + mNotificationStackScroller.getWidth();
+ float stackScrollerX = mNotificationStackScrollLayoutController.getX();
+ return !mNotificationStackScrollLayoutController
+ .isBelowLastNotification(x - stackScrollerX, y)
+ && stackScrollerX < x
+ && x < stackScrollerX + mNotificationStackScrollLayoutController.getWidth();
}
private void initDownStates(MotionEvent event) {
@@ -1254,7 +1281,7 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
protected float getOpeningHeight() {
- return mNotificationStackScroller.getOpeningHeight();
+ return mNotificationStackScrollLayoutController.getOpeningHeight();
}
@@ -1290,7 +1317,7 @@ public class NotificationPanelViewController extends PanelViewController {
< mStatusBarMinHeight) {
mMetricsLogger.count(COUNTER_PANEL_OPEN_QS, 1);
mQsExpandImmediate = true;
- mNotificationStackScroller.setShouldShowShelfOnly(true);
+ mNotificationStackScrollLayoutController.setShouldShowShelfOnly(true);
requestPanelHeightUpdate();
// Normally, we start listening when the panel is expanded, but here we need to start
@@ -1302,7 +1329,7 @@ public class NotificationPanelViewController extends PanelViewController {
private boolean isInQsArea(float x, float y) {
return (x >= mQsFrame.getX() && x <= mQsFrame.getX() + mQsFrame.getWidth()) && (
- y <= mNotificationStackScroller.getBottomMostNotificationBottom()
+ y <= mNotificationStackScrollLayoutController.getBottomMostNotificationBottom()
|| y <= mQs.getView().getY() + mQs.getView().getHeight());
}
@@ -1492,7 +1519,7 @@ public class NotificationPanelViewController extends PanelViewController {
float height = mQsExpansionHeight - overscrollAmount;
setQsExpansion(height);
requestPanelHeightUpdate();
- mNotificationStackScroller.checkSnoozeLeavebehind();
+ mNotificationStackScrollLayoutController.checkSnoozeLeavebehind();
// When expanding QS, let's authenticate the user if possible,
// this will speed up notification actions.
@@ -1665,8 +1692,8 @@ public class NotificationPanelViewController extends PanelViewController {
}
private void updateQsState() {
- mNotificationStackScroller.setQsExpanded(mQsExpanded);
- mNotificationStackScroller.setScrollingEnabled(
+ mNotificationStackScrollLayoutController.setQsExpanded(mQsExpanded);
+ mNotificationStackScrollLayoutController.setScrollingEnabled(
mBarState != StatusBarState.KEYGUARD && (!mQsExpanded
|| mQsExpansionFromOverscroll));
updateEmptyShadeView();
@@ -1726,7 +1753,7 @@ public class NotificationPanelViewController extends PanelViewController {
float qsExpansionFraction = getQsExpansionFraction();
mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation());
mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
- mNotificationStackScroller.setQsExpansionFraction(qsExpansionFraction);
+ mNotificationStackScrollLayoutController.setQsExpansionFraction(qsExpansionFraction);
}
private String determineAccessibilityPaneTitle() {
@@ -1785,18 +1812,18 @@ public class NotificationPanelViewController extends PanelViewController {
return mClockPositionResult.stackScrollerPadding;
}
int collapsedPosition = mHeadsUpInset;
- if (!mNotificationStackScroller.isPulseExpanding()) {
+ if (!mNotificationStackScrollLayoutController.isPulseExpanding()) {
return collapsedPosition;
} else {
int expandedPosition = mClockPositionResult.stackScrollerPadding;
return (int) MathUtils.lerp(collapsedPosition, expandedPosition,
- mNotificationStackScroller.calculateAppearFractionBypass());
+ mNotificationStackScrollLayoutController.calculateAppearFractionBypass());
}
}
protected void requestScrollerTopPaddingUpdate(boolean animate) {
- mNotificationStackScroller.updateTopPadding(calculateQsTopPadding(), animate);
+ mNotificationStackScrollLayoutController.updateTopPadding(calculateQsTopPadding(), animate);
if (mKeyguardShowing && mKeyguardBypassController.getBypassEnabled()) {
// update the position of the header
updateQsExpansion();
@@ -1808,7 +1835,7 @@ public class NotificationPanelViewController extends PanelViewController {
if (mQs != null) {
mQs.setShowCollapsedOnKeyguard(
mKeyguardShowing && mKeyguardBypassController.getBypassEnabled()
- && mNotificationStackScroller.isPulseExpanding());
+ && mNotificationStackScrollLayoutController.isPulseExpanding());
}
}
@@ -1904,7 +1931,7 @@ public class NotificationPanelViewController extends PanelViewController {
public void onAnimationEnd(Animator animation) {
mAnimatingQS = false;
notifyExpandingFinished();
- mNotificationStackScroller.resetCheckSnoozeLeavebehind();
+ mNotificationStackScrollLayoutController.resetCheckSnoozeLeavebehind();
mQsExpansionAnimator = null;
if (onFinishRunnable != null) {
onFinishRunnable.run();
@@ -1943,8 +1970,8 @@ public class NotificationPanelViewController extends PanelViewController {
protected boolean canCollapsePanelOnTouch() {
if (!isInSettings()) {
return mBarState == StatusBarState.KEYGUARD
- || mNotificationStackScroller.isScrolledToBottom()
- || mIsPanelCollapseOnQQS;
+ || mIsPanelCollapseOnQQS
+ || mNotificationStackScrollLayoutController.isScrolledToBottom();
} else {
return true;
}
@@ -1962,7 +1989,7 @@ public class NotificationPanelViewController extends PanelViewController {
private int getMaxPanelHeightNonBypass() {
int min = mStatusBarMinHeight;
if (!(mBarState == StatusBarState.KEYGUARD)
- && mNotificationStackScroller.getNotGoneChildCount() == 0) {
+ && mNotificationStackScrollLayoutController.getNotGoneChildCount() == 0) {
int minHeight = (int) (mQsMinExpansionHeight + getOverExpansionAmount());
min = Math.max(min, minHeight);
}
@@ -1988,7 +2015,7 @@ public class NotificationPanelViewController extends PanelViewController {
int position =
mClockPositionAlgorithm.getExpandedClockPosition()
+ mKeyguardStatusView.getHeight();
- if (mNotificationStackScroller.getVisibleNotificationCount() != 0) {
+ if (mNotificationStackScrollLayoutController.getVisibleNotificationCount() != 0) {
position += mShelfHeight / 2.0f + mDarkIconSize / 2.0f;
}
return position;
@@ -2027,8 +2054,8 @@ public class NotificationPanelViewController extends PanelViewController {
// minimum QS expansion + minStackHeight
float
panelHeightQsCollapsed =
- mNotificationStackScroller.getIntrinsicPadding()
- + mNotificationStackScroller.getLayoutMinHeight();
+ mNotificationStackScrollLayoutController.getIntrinsicPadding()
+ + mNotificationStackScrollLayoutController.getLayoutMinHeight();
float panelHeightQsExpanded = calculatePanelHeightQsExpanded();
t =
(expandedHeight - panelHeightQsCollapsed) / (panelHeightQsExpanded
@@ -2060,16 +2087,16 @@ public class NotificationPanelViewController extends PanelViewController {
}
private int calculatePanelHeightShade() {
- int emptyBottomMargin = mNotificationStackScroller.getEmptyBottomMargin();
- int maxHeight = mNotificationStackScroller.getHeight() - emptyBottomMargin;
- maxHeight += mNotificationStackScroller.getTopPaddingOverflow();
+ int emptyBottomMargin = mNotificationStackScrollLayoutController.getEmptyBottomMargin();
+ int maxHeight = mNotificationStackScrollLayoutController.getHeight() - emptyBottomMargin;
+ maxHeight += mNotificationStackScrollLayoutController.getTopPaddingOverflow();
if (mBarState == StatusBarState.KEYGUARD) {
int
minKeyguardPanelBottom =
mClockPositionAlgorithm.getExpandedClockPosition()
+ mKeyguardStatusView.getHeight()
- + mNotificationStackScroller.getIntrinsicContentHeight();
+ + mNotificationStackScrollLayoutController.getIntrinsicContentHeight();
return Math.max(maxHeight, minKeyguardPanelBottom);
} else {
return maxHeight;
@@ -2079,15 +2106,16 @@ public class NotificationPanelViewController extends PanelViewController {
private int calculatePanelHeightQsExpanded() {
float
notificationHeight =
- mNotificationStackScroller.getHeight()
- - mNotificationStackScroller.getEmptyBottomMargin()
- - mNotificationStackScroller.getTopPadding();
+ mNotificationStackScrollLayoutController.getHeight()
+ - mNotificationStackScrollLayoutController.getEmptyBottomMargin()
+ - mNotificationStackScrollLayoutController.getTopPadding();
// When only empty shade view is visible in QS collapsed state, simulate that we would have
// it in expanded QS state as well so we don't run into troubles when fading the view in/out
// and expanding/collapsing the whole panel from/to quick settings.
- if (mNotificationStackScroller.getNotGoneChildCount() == 0 && mShowEmptyShadeView) {
- notificationHeight = mNotificationStackScroller.getEmptyShadeViewHeight();
+ if (mNotificationStackScrollLayoutController.getNotGoneChildCount() == 0
+ && mShowEmptyShadeView) {
+ notificationHeight = mNotificationStackScrollLayoutController.getEmptyShadeViewHeight();
}
int maxQsHeight = mQsMaxExpansionHeight;
@@ -2102,12 +2130,13 @@ public class NotificationPanelViewController extends PanelViewController {
float totalHeight = Math.max(maxQsHeight,
mBarState == StatusBarState.KEYGUARD ? mClockPositionResult.stackScrollerPadding
: 0) + notificationHeight
- + mNotificationStackScroller.getTopPaddingOverflow();
- if (totalHeight > mNotificationStackScroller.getHeight()) {
+ + mNotificationStackScrollLayoutController.getTopPaddingOverflow();
+ if (totalHeight > mNotificationStackScrollLayoutController.getHeight()) {
float
fullyCollapsedHeight =
- maxQsHeight + mNotificationStackScroller.getLayoutMinHeight();
- totalHeight = Math.max(fullyCollapsedHeight, mNotificationStackScroller.getHeight());
+ maxQsHeight + mNotificationStackScrollLayoutController.getLayoutMinHeight();
+ totalHeight = Math.max(fullyCollapsedHeight,
+ mNotificationStackScrollLayoutController.getHeight());
}
return (int) totalHeight;
}
@@ -2122,7 +2151,7 @@ public class NotificationPanelViewController extends PanelViewController {
&& !mKeyguardBypassController.getBypassEnabled()) {
alpha *= mClockPositionResult.clockAlpha;
}
- mNotificationStackScroller.setAlpha(alpha);
+ mNotificationStackScrollLayoutController.setAlpha(alpha);
}
private float getFadeoutAlpha() {
@@ -2138,7 +2167,8 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
protected float getOverExpansionAmount() {
- float result = mNotificationStackScroller.getCurrentOverScrollAmount(true /* top */);
+ float result = mNotificationStackScrollLayoutController
+ .getCurrentOverScrollAmount(true /* top */);
if (isNaN(result)) {
Log.wtf(TAG, "OverExpansionAmount is NaN!");
}
@@ -2148,7 +2178,8 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
protected float getOverExpansionPixels() {
- return mNotificationStackScroller.getCurrentOverScrolledPixels(true /* top */);
+ return mNotificationStackScrollLayoutController
+ .getCurrentOverScrolledPixels(true /* top */);
}
/**
@@ -2165,17 +2196,19 @@ public class NotificationPanelViewController extends PanelViewController {
if (mBarState == StatusBarState.KEYGUARD && !mKeyguardBypassController.getBypassEnabled()) {
return -mQs.getQsMinExpansionHeight();
}
- float appearAmount = mNotificationStackScroller.calculateAppearFraction(mExpandedHeight);
+ float appearAmount = mNotificationStackScrollLayoutController
+ .calculateAppearFraction(mExpandedHeight);
float startHeight = -mQsExpansionHeight;
if (mKeyguardBypassController.getBypassEnabled() && isOnKeyguard()
- && mNotificationStackScroller.isPulseExpanding()) {
+ && mNotificationStackScrollLayoutController.isPulseExpanding()) {
if (!mPulseExpansionHandler.isExpanding()
&& !mPulseExpansionHandler.getLeavingLockscreen()) {
// If we aborted the expansion we need to make sure the header doesn't reappear
// again after the header has animated away
appearAmount = 0;
} else {
- appearAmount = mNotificationStackScroller.calculateAppearFractionBypass();
+ appearAmount = mNotificationStackScrollLayoutController
+ .calculateAppearFractionBypass();
}
startHeight = -mQs.getQsMinExpansionHeight();
}
@@ -2264,7 +2297,7 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
protected void onExpandingStarted() {
super.onExpandingStarted();
- mNotificationStackScroller.onExpansionStarted();
+ mNotificationStackScrollLayoutController.onExpansionStarted();
mIsExpanding = true;
mQsExpandedWhenExpandingStarted = mQsFullyExpanded;
mMediaHierarchyManager.setCollapsingShadeFromQS(mQsExpandedWhenExpandingStarted &&
@@ -2282,7 +2315,7 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
protected void onExpandingFinished() {
super.onExpandingFinished();
- mNotificationStackScroller.onExpansionStopped();
+ mNotificationStackScrollLayoutController.onExpansionStopped();
mHeadsUpManager.onExpandingFinished();
mConversationNotificationManager.onNotificationPanelExpandStateChanged(isFullyCollapsed());
mIsExpanding = false;
@@ -2308,7 +2341,7 @@ public class NotificationPanelViewController extends PanelViewController {
setListening(true);
}
mQsExpandImmediate = false;
- mNotificationStackScroller.setShouldShowShelfOnly(false);
+ mNotificationStackScrollLayoutController.setShouldShowShelfOnly(false);
mTwoFingerQsExpandPossible = false;
notifyListenersTrackingHeadsUp(null);
mExpandingFromHeadsUp = false;
@@ -2340,15 +2373,16 @@ public class NotificationPanelViewController extends PanelViewController {
return;
}
if (mBarState != StatusBarState.KEYGUARD) {
- mNotificationStackScroller.setOnHeightChangedListener(null);
+ mNotificationStackScrollLayoutController.setOnHeightChangedListener(null);
if (isPixels) {
- mNotificationStackScroller.setOverScrolledPixels(overExpansion, true /* onTop */,
- false /* animate */);
+ mNotificationStackScrollLayoutController.setOverScrolledPixels(
+ overExpansion, true /* onTop */, false /* animate */);
} else {
- mNotificationStackScroller.setOverScrollAmount(overExpansion, true /* onTop */,
- false /* animate */);
+ mNotificationStackScrollLayoutController.setOverScrollAmount(
+ overExpansion, true /* onTop */, false /* animate */);
}
- mNotificationStackScroller.setOnHeightChangedListener(mOnHeightChangedListener);
+ mNotificationStackScrollLayoutController
+ .setOnHeightChangedListener(mOnHeightChangedListener);
}
}
@@ -2358,12 +2392,12 @@ public class NotificationPanelViewController extends PanelViewController {
super.onTrackingStarted();
if (mQsFullyExpanded) {
mQsExpandImmediate = true;
- mNotificationStackScroller.setShouldShowShelfOnly(true);
+ mNotificationStackScrollLayoutController.setShouldShowShelfOnly(true);
}
if (mBarState == StatusBarState.KEYGUARD || mBarState == StatusBarState.SHADE_LOCKED) {
mAffordanceHelper.animateHideLeftRightIcon();
}
- mNotificationStackScroller.onPanelTrackingStarted();
+ mNotificationStackScrollLayoutController.onPanelTrackingStarted();
}
@Override
@@ -2371,10 +2405,10 @@ public class NotificationPanelViewController extends PanelViewController {
mFalsingManager.onTrackingStopped();
super.onTrackingStopped(expand);
if (expand) {
- mNotificationStackScroller.setOverScrolledPixels(0.0f, true /* onTop */,
+ mNotificationStackScrollLayoutController.setOverScrolledPixels(0.0f, true /* onTop */,
true /* animate */);
}
- mNotificationStackScroller.onPanelTrackingStopped();
+ mNotificationStackScrollLayoutController.onPanelTrackingStopped();
if (expand && (mBarState == StatusBarState.KEYGUARD
|| mBarState == StatusBarState.SHADE_LOCKED)) {
if (!mHintAnimationRunning) {
@@ -2384,7 +2418,8 @@ public class NotificationPanelViewController extends PanelViewController {
}
private void updateMaxHeadsUpTranslation() {
- mNotificationStackScroller.setHeadsUpBoundaries(getHeight(), mNavigationBarBottomHeight);
+ mNotificationStackScrollLayoutController.setHeadsUpBoundaries(
+ getHeight(), mNavigationBarBottomHeight);
}
@Override
@@ -2400,19 +2435,19 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
protected void onUnlockHintFinished() {
super.onUnlockHintFinished();
- mNotificationStackScroller.setUnlockHintRunning(false);
+ mNotificationStackScrollLayoutController.setUnlockHintRunning(false);
}
@Override
protected void onUnlockHintStarted() {
super.onUnlockHintStarted();
- mNotificationStackScroller.setUnlockHintRunning(true);
+ mNotificationStackScrollLayoutController.setUnlockHintRunning(true);
}
@Override
protected float getPeekHeight() {
- if (mNotificationStackScroller.getNotGoneChildCount() > 0) {
- return mNotificationStackScroller.getPeekHeight();
+ if (mNotificationStackScrollLayoutController.getNotGoneChildCount() > 0) {
+ return mNotificationStackScrollLayoutController.getPeekHeight();
} else {
return mQsMinExpansionHeight;
}
@@ -2426,7 +2461,8 @@ public class NotificationPanelViewController extends PanelViewController {
}
// Let's make sure we're not appearing but the animation will end below the appear.
// Otherwise quick settings would jump at the end of the animation.
- float fraction = mNotificationStackScroller.calculateAppearFraction(targetHeight);
+ float fraction = mNotificationStackScrollLayoutController
+ .calculateAppearFraction(targetHeight);
return fraction >= 1.0f;
}
@@ -2438,18 +2474,19 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
protected boolean fullyExpandedClearAllVisible() {
- return mNotificationStackScroller.isFooterViewNotGone()
- && mNotificationStackScroller.isScrolledToBottom() && !mQsExpandImmediate;
+ return mNotificationStackScrollLayoutController.isFooterViewNotGone()
+ && mNotificationStackScrollLayoutController.isScrolledToBottom()
+ && !mQsExpandImmediate;
}
@Override
protected boolean isClearAllVisible() {
- return mNotificationStackScroller.isFooterViewContentVisible();
+ return mNotificationStackScrollLayoutController.isFooterViewContentVisible();
}
@Override
protected int getClearAllHeightWithPadding() {
- return mNotificationStackScroller.getFooterViewHeightWithPadding();
+ return mNotificationStackScrollLayoutController.getFooterViewHeightWithPadding();
}
@Override
@@ -2500,7 +2537,8 @@ public class NotificationPanelViewController extends PanelViewController {
private void updateEmptyShadeView() {
// Hide "No notifications" in QS.
- mNotificationStackScroller.updateEmptyShadeView(mShowEmptyShadeView && !mQsExpanded);
+ mNotificationStackScrollLayoutController.updateEmptyShadeView(
+ mShowEmptyShadeView && !mQsExpanded);
}
public void setQsScrimEnabled(boolean qsScrimEnabled) {
@@ -2591,7 +2629,7 @@ public class NotificationPanelViewController extends PanelViewController {
public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
mHeadsUpAnimatingAway = headsUpAnimatingAway;
- mNotificationStackScroller.setHeadsUpAnimatingAway(headsUpAnimatingAway);
+ mNotificationStackScrollLayoutController.setHeadsUpAnimatingAway(headsUpAnimatingAway);
updateHeadsUpVisibility();
}
@@ -2603,7 +2641,7 @@ public class NotificationPanelViewController extends PanelViewController {
public void setHeadsUpManager(HeadsUpManagerPhone headsUpManager) {
super.setHeadsUpManager(headsUpManager);
mHeadsUpTouchHelper = new HeadsUpTouchHelper(headsUpManager,
- mNotificationStackScroller.getHeadsUpCallback(),
+ mNotificationStackScrollLayoutController.getHeadsUpCallback(),
NotificationPanelViewController.this);
}
@@ -2625,7 +2663,7 @@ public class NotificationPanelViewController extends PanelViewController {
private void setClosingWithAlphaFadeout(boolean closing) {
mClosingWithAlphaFadeOut = closing;
- mNotificationStackScroller.forceNoOverlappingRendering(closing);
+ mNotificationStackScrollLayoutController.forceNoOverlappingRendering(closing);
}
/**
@@ -2635,22 +2673,24 @@ public class NotificationPanelViewController extends PanelViewController {
* @param x the x-coordinate the touch event
*/
protected void updateVerticalPanelPosition(float x) {
- if (mNotificationStackScroller.getWidth() * 1.75f > mView.getWidth()) {
+ if (mNotificationStackScrollLayoutController.getWidth() * 1.75f > mView.getWidth()) {
resetHorizontalPanelPosition();
return;
}
- float leftMost = mPositionMinSideMargin + mNotificationStackScroller.getWidth() / 2;
+ float leftMost = mPositionMinSideMargin
+ + mNotificationStackScrollLayoutController.getWidth() / 2;
float
rightMost =
mView.getWidth() - mPositionMinSideMargin
- - mNotificationStackScroller.getWidth() / 2;
- if (Math.abs(x - mView.getWidth() / 2) < mNotificationStackScroller.getWidth() / 4) {
+ - mNotificationStackScrollLayoutController.getWidth() / 2;
+ if (Math.abs(x - mView.getWidth() / 2)
+ < mNotificationStackScrollLayoutController.getWidth() / 4) {
x = mView.getWidth() / 2;
}
x = Math.min(rightMost, Math.max(leftMost, x));
float
- center =
- mNotificationStackScroller.getLeft() + mNotificationStackScroller.getWidth() / 2;
+ center = mNotificationStackScrollLayoutController.getLeft()
+ + mNotificationStackScrollLayoutController.getWidth() / 2;
setHorizontalPanelTranslation(x - center);
}
@@ -2659,7 +2699,7 @@ public class NotificationPanelViewController extends PanelViewController {
}
protected void setHorizontalPanelTranslation(float translation) {
- mNotificationStackScroller.setTranslationX(translation);
+ mNotificationStackScrollLayoutController.setTranslationX(translation);
mQsFrame.setTranslationX(translation);
int size = mVerticalTranslationListener.size();
for (int i = 0; i < size; i++) {
@@ -2669,13 +2709,14 @@ public class NotificationPanelViewController extends PanelViewController {
protected void updateExpandedHeight(float expandedHeight) {
if (mTracking) {
- mNotificationStackScroller.setExpandingVelocity(getCurrentExpandVelocity());
+ mNotificationStackScrollLayoutController
+ .setExpandingVelocity(getCurrentExpandVelocity());
}
if (mKeyguardBypassController.getBypassEnabled() && isOnKeyguard()) {
// The expandedHeight is always the full panel Height when bypassing
expandedHeight = getMaxPanelHeightNonBypass();
}
- mNotificationStackScroller.setExpandedHeight(expandedHeight);
+ mNotificationStackScrollLayoutController.setExpandedHeight(expandedHeight);
updateKeyguardBottomAreaAlpha();
updateBigClockAlpha();
updateStatusBarIcons();
@@ -2835,7 +2876,7 @@ public class NotificationPanelViewController extends PanelViewController {
mHeightListener.onQsHeightChanged();
}
});
- mNotificationStackScroller.setQsContainer((ViewGroup) mQs.getView());
+ mNotificationStackScrollLayoutController.setQsContainer((ViewGroup) mQs.getView());
if (mQs instanceof QSFragment) {
mKeyguardStatusBar.setQSPanel(((QSFragment) mQs).getQsPanel());
}
@@ -2859,7 +2900,7 @@ public class NotificationPanelViewController extends PanelViewController {
if (disabled && mAffordanceHelper.isSwipingInProgress() && !mIsLaunchTransitionRunning) {
mAffordanceHelper.reset(false /* animate */);
}
- mNotificationStackScroller.setAnimationsEnabled(!disabled);
+ mNotificationStackScrollLayoutController.setAnimationsEnabled(!disabled);
}
/**
@@ -2873,7 +2914,7 @@ public class NotificationPanelViewController extends PanelViewController {
if (dozing == mDozing) return;
mView.setDozing(dozing);
mDozing = dozing;
- mNotificationStackScroller.setDozing(mDozing, animate, wakeUpTouchLocation);
+ mNotificationStackScrollLayoutController.setDozing(mDozing, animate, wakeUpTouchLocation);
mKeyguardBottomArea.setDozing(mDozing, animate);
if (dozing) {
@@ -2901,7 +2942,7 @@ public class NotificationPanelViewController extends PanelViewController {
if (!mPulsing && !mDozing) {
mAnimateNextPositionUpdate = false;
}
- mNotificationStackScroller.setPulsing(pulsing, animatePulse);
+ mNotificationStackScrollLayoutController.setPulsing(pulsing, animatePulse);
mKeyguardStatusView.setPulsing(pulsing);
}
@@ -3006,7 +3047,7 @@ public class NotificationPanelViewController extends PanelViewController {
}
public boolean hasActiveClearableNotifications() {
- return mNotificationStackScroller.hasActiveClearableNotifications(ROWS_ALL);
+ return mNotificationStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL);
}
private void updateShowEmptyShadeView() {
@@ -3017,54 +3058,57 @@ public class NotificationPanelViewController extends PanelViewController {
}
public RemoteInputController.Delegate createRemoteInputDelegate() {
- return mNotificationStackScroller.createDelegate();
+ return mNotificationStackScrollLayoutController.createDelegate();
}
void updateNotificationViews(String reason) {
- mNotificationStackScroller.updateSectionBoundaries(reason);
- mNotificationStackScroller.updateSpeedBumpIndex();
- mNotificationStackScroller.updateFooter();
+ mNotificationStackScrollLayoutController.updateSectionBoundaries(reason);
+ mNotificationStackScrollLayoutController.updateSpeedBumpIndex();
+ mNotificationStackScrollLayoutController.updateFooter();
updateShowEmptyShadeView();
- mNotificationStackScroller.updateIconAreaViews();
+ mNotificationStackScrollLayoutController.updateIconAreaViews();
}
public void onUpdateRowStates() {
- mNotificationStackScroller.onUpdateRowStates();
+ mNotificationStackScrollLayoutController.onUpdateRowStates();
}
public boolean hasPulsingNotifications() {
- return mNotificationStackScroller.hasPulsingNotifications();
+ return mNotificationStackScrollLayoutController
+ .getNotificationListContainer().hasPulsingNotifications();
}
public ActivatableNotificationView getActivatedChild() {
- return mNotificationStackScroller.getActivatedChild();
+ return mNotificationStackScrollLayoutController.getActivatedChild();
}
public void setActivatedChild(ActivatableNotificationView o) {
- mNotificationStackScroller.setActivatedChild(o);
+ mNotificationStackScrollLayoutController.setActivatedChild(o);
}
public void runAfterAnimationFinished(Runnable r) {
- mNotificationStackScroller.runAfterAnimationFinished(r);
+ mNotificationStackScrollLayoutController.runAfterAnimationFinished(r);
}
public void setScrollingEnabled(boolean b) {
- mNotificationStackScroller.setScrollingEnabled(b);
+ mNotificationStackScrollLayoutController.setScrollingEnabled(b);
}
public void initDependencies(StatusBar statusBar, NotificationGroupManager groupManager,
- NotificationShelf notificationShelf,
+ NotificationShelfController notificationShelfController,
NotificationIconAreaController notificationIconAreaController,
ScrimController scrimController) {
setStatusBar(statusBar);
setGroupManager(mGroupManager);
- mNotificationStackScroller.setNotificationPanelController(this);
- mNotificationStackScroller.setIconAreaController(notificationIconAreaController);
- mNotificationStackScroller.setStatusBar(statusBar);
- mNotificationStackScroller.setGroupManager(groupManager);
- mNotificationStackScroller.setShelf(notificationShelf);
- mNotificationStackScroller.setScrimController(scrimController);
+ mNotificationStackScrollLayoutController.setNotificationPanelController(this);
+ mNotificationStackScrollLayoutController
+ .setIconAreaController(notificationIconAreaController);
+ mNotificationStackScrollLayoutController.setStatusBar(statusBar);
+ mNotificationStackScrollLayoutController.setGroupManager(groupManager);
+ mNotificationStackScrollLayoutController.setShelfController(notificationShelfController);
+ mNotificationStackScrollLayoutController.setScrimController(scrimController);
updateShowEmptyShadeView();
+ mNotificationShelfController = notificationShelfController;
}
public void showTransientIndication(int id) {
@@ -3216,6 +3260,10 @@ public class NotificationPanelViewController extends PanelViewController {
return new OnConfigurationChangedListener();
}
+ public NotificationStackScrollLayoutController getNotificationStackScrollLayoutController() {
+ return mNotificationStackScrollLayoutController;
+ }
+
private class OnHeightChangedListener implements ExpandableView.OnHeightChangedListener {
@Override
public void onHeightChanged(ExpandableView view, boolean needsAnimation) {
@@ -3228,7 +3276,8 @@ public class NotificationPanelViewController extends PanelViewController {
if (needsAnimation && mInterpolatedDarkAmount == 0) {
mAnimateNextPositionUpdate = true;
}
- ExpandableView firstChildNotGone = mNotificationStackScroller.getFirstChildNotGone();
+ ExpandableView firstChildNotGone =
+ mNotificationStackScrollLayoutController.getFirstChildNotGone();
ExpandableNotificationRow
firstRow =
firstChildNotGone instanceof ExpandableNotificationRow
@@ -3454,13 +3503,13 @@ public class NotificationPanelViewController extends PanelViewController {
private class MyOnHeadsUpChangedListener implements OnHeadsUpChangedListener {
@Override
public void onHeadsUpPinnedModeChanged(final boolean inPinnedMode) {
- mNotificationStackScroller.setInHeadsUpPinnedMode(inPinnedMode);
+ mNotificationStackScrollLayoutController.setInHeadsUpPinnedMode(inPinnedMode);
if (inPinnedMode) {
mHeadsUpExistenceChangedRunnable.run();
updateNotificationTranslucency();
} else {
setHeadsUpAnimatingAway(true);
- mNotificationStackScroller.runAfterAnimationFinished(
+ mNotificationStackScrollLayoutController.runAfterAnimationFinished(
mHeadsUpExistenceChangedRunnable);
}
updateGestureExclusionRect();
@@ -3472,8 +3521,8 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
public void onHeadsUpPinned(NotificationEntry entry) {
if (!isOnKeyguard()) {
- mNotificationStackScroller.generateHeadsUpAnimation(entry.getHeadsUpAnimationView(),
- true);
+ mNotificationStackScrollLayoutController.generateHeadsUpAnimation(
+ entry.getHeadsUpAnimationView(), true);
}
}
@@ -3485,7 +3534,7 @@ public class NotificationPanelViewController extends PanelViewController {
// notification
// will stick to the top without any interaction.
if (isFullyCollapsed() && entry.isRowHeadsUp() && !isOnKeyguard()) {
- mNotificationStackScroller.generateHeadsUpAnimation(
+ mNotificationStackScrollLayoutController.generateHeadsUpAnimation(
entry.getHeadsUpAnimationView(), false);
entry.setHeadsUpIsVisible();
}
@@ -3493,7 +3542,7 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
- mNotificationStackScroller.generateHeadsUpAnimation(entry, isHeadsUp);
+ mNotificationStackScrollLayoutController.generateHeadsUpAnimation(entry, isHeadsUp);
}
}
@@ -3508,7 +3557,7 @@ public class NotificationPanelViewController extends PanelViewController {
if (mAccessibilityManager.isEnabled()) {
mView.setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
}
- mNotificationStackScroller.setMaxTopPadding(
+ mNotificationStackScrollLayoutController.setMaxTopPadding(
mQsMaxExpansionHeight + mQsNotificationTopPadding);
}
}
@@ -3570,7 +3619,7 @@ public class NotificationPanelViewController extends PanelViewController {
} else if (oldState == StatusBarState.SHADE_LOCKED
&& statusBarState == StatusBarState.KEYGUARD) {
animateKeyguardStatusBarIn(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- mNotificationStackScroller.resetScrollPosition();
+ mNotificationStackScrollLayoutController.resetScrollPosition();
// Only animate header if the header is visible. If not, it will partially
// animate out
// the top of QS
@@ -3646,7 +3695,7 @@ public class NotificationPanelViewController extends PanelViewController {
int oldTop, int oldRight, int oldBottom) {
DejankUtils.startDetectingBlockingIpcs("NVP#onLayout");
super.onLayoutChange(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom);
- setIsFullWidth(mNotificationStackScroller.getWidth() == mView.getWidth());
+ setIsFullWidth(mNotificationStackScrollLayoutController.getWidth() == mView.getWidth());
// Update Clock Pivot
mKeyguardStatusView.setPivotX(mView.getWidth() / 2);
@@ -3662,7 +3711,7 @@ public class NotificationPanelViewController extends PanelViewController {
mQsExpansionHeight = mQsMinExpansionHeight;
}
mQsMaxExpansionHeight = mQs.getDesiredHeight();
- mNotificationStackScroller.setMaxTopPadding(
+ mNotificationStackScrollLayoutController.setMaxTopPadding(
mQsMaxExpansionHeight + mQsNotificationTopPadding);
}
positionClockAndNotifications();
@@ -3724,7 +3773,7 @@ public class NotificationPanelViewController extends PanelViewController {
0, calculateQsTopPadding(), mView.getWidth(), calculateQsTopPadding(), p);
p.setColor(Color.CYAN);
canvas.drawLine(0, mClockPositionResult.stackScrollerPadding, mView.getWidth(),
- mNotificationStackScroller.getTopPadding(), p);
+ mNotificationStackScrollLayoutController.getTopPadding(), p);
p.setColor(Color.GRAY);
canvas.drawLine(0, mClockPositionResult.clockY, mView.getWidth(),
mClockPositionResult.clockY, p);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 8cb54eef01b4..e42c3dc4f589 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -284,13 +284,22 @@ public class PhoneStatusBarPolicy
mResources.getString(R.string.accessibility_data_saver_on));
mIconController.setIconVisibility(mSlotDataSaver, false);
+
// privacy items
+ String microphoneString = mResources.getString(PrivacyType.TYPE_MICROPHONE.getNameId());
+ String microphoneDesc = mResources.getString(
+ R.string.ongoing_privacy_chip_content_multiple_apps, microphoneString);
mIconController.setIcon(mSlotMicrophone, PrivacyType.TYPE_MICROPHONE.getIconId(),
- mResources.getString(PrivacyType.TYPE_MICROPHONE.getNameId()));
+ microphoneDesc);
mIconController.setIconVisibility(mSlotMicrophone, false);
+
+ String cameraString = mResources.getString(PrivacyType.TYPE_CAMERA.getNameId());
+ String cameraDesc = mResources.getString(
+ R.string.ongoing_privacy_chip_content_multiple_apps, cameraString);
mIconController.setIcon(mSlotCamera, PrivacyType.TYPE_CAMERA.getIconId(),
- mResources.getString(PrivacyType.TYPE_CAMERA.getNameId()));
+ cameraDesc);
mIconController.setIconVisibility(mSlotCamera, false);
+
mIconController.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID,
mResources.getString(R.string.accessibility_location_active));
mIconController.setIconVisibility(mSlotLocation, false);
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 eb626280b494..aa8985f43be0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -179,7 +179,6 @@ import com.android.systemui.statusbar.AutoHideUiElement;
import com.android.systemui.statusbar.BackDropView;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CrossFadeHelper;
-import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.GestureRecorder;
import com.android.systemui.statusbar.KeyboardShortcuts;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -189,7 +188,7 @@ import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
-import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.ScrimView;
@@ -210,6 +209,8 @@ import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule;
import com.android.systemui.statusbar.policy.BatteryController;
@@ -646,6 +647,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private final BubbleController.BubbleExpandListener mBubbleExpandListener;
private ActivityIntentHelper mActivityIntentHelper;
+ private NotificationStackScrollLayoutController mStackScrollerController;
/**
* Public constructor for StatusBar.
@@ -1016,9 +1018,11 @@ public class StatusBar extends SystemUI implements DemoMode,
// TODO: Deal with the ugliness that comes from having some of the statusbar broken out
// into fragments, but the rest here, it leaves some awkward lifecycle and whatnot.
- mStackScroller = mNotificationShadeWindowView.findViewById(
- R.id.notification_stack_scroller);
- NotificationListContainer notifListContainer = (NotificationListContainer) mStackScroller;
+ mStackScrollerController =
+ mNotificationPanelViewController.getNotificationStackScrollLayoutController();
+ mStackScroller = mStackScrollerController.getView();
+ NotificationListContainer notifListContainer =
+ mStackScrollerController.getNotificationListContainer();
mNotificationLogger.setUpWithContainer(notifListContainer);
// TODO: make this injectable. Currently that would create a circular dependency between
@@ -1029,7 +1033,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mStatusBarStateController);
mWakeUpCoordinator.setIconAreaController(mNotificationIconAreaController);
inflateShelf();
- mNotificationIconAreaController.setupShelf(mNotificationShelf);
+ mNotificationIconAreaController.setupShelf(mNotificationShelfController);
mNotificationPanelViewController.setOnReinflationListener(
mNotificationIconAreaController::initAodIcons);
mNotificationPanelViewController.addExpansionListener(mWakeUpCoordinator);
@@ -1076,7 +1080,7 @@ public class StatusBar extends SystemUI implements DemoMode,
// TODO (b/136993073) Separate notification shade and status bar
mHeadsUpAppearanceController = new HeadsUpAppearanceController(
mNotificationIconAreaController, mHeadsUpManager,
- mNotificationShadeWindowView,
+ mStackScroller.getController(),
mStatusBarStateController, mKeyguardBypassController,
mKeyguardStateController, mWakeUpCoordinator, mCommandQueue,
mNotificationPanelViewController, mStatusBarView);
@@ -1147,7 +1151,8 @@ public class StatusBar extends SystemUI implements DemoMode,
});
mScrimController.attachViews(scrimBehind, scrimInFront, scrimForBubble);
- mNotificationPanelViewController.initDependencies(this, mGroupManager, mNotificationShelf,
+ mNotificationPanelViewController.initDependencies(this, mGroupManager,
+ mNotificationShelfController,
mNotificationIconAreaController, mScrimController);
BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop);
@@ -1300,17 +1305,19 @@ public class StatusBar extends SystemUI implements DemoMode,
mActivityLaunchAnimator = new ActivityLaunchAnimator(
mNotificationShadeWindowViewController, this, mNotificationPanelViewController,
mNotificationShadeDepthControllerLazy.get(),
- (NotificationListContainer) mStackScroller, mContext.getMainExecutor());
+ mStackScrollerController.getNotificationListContainer(),
+ mContext.getMainExecutor());
// TODO: inject this.
mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanelViewController,
- mHeadsUpManager, mNotificationShadeWindowView, mStackScroller, mDozeScrimController,
- mScrimController, mActivityLaunchAnimator, mDynamicPrivacyController,
- mKeyguardStateController, mKeyguardIndicationController,
+ mHeadsUpManager, mNotificationShadeWindowView, mStackScrollerController,
+ mDozeScrimController, mScrimController, mActivityLaunchAnimator,
+ mDynamicPrivacyController, mKeyguardStateController,
+ mKeyguardIndicationController,
this /* statusBar */, mShadeController, mCommandQueue, mInitController,
mNotificationInterruptStateProvider);
- mNotificationShelf.setOnActivatedListener(mPresenter);
+ mNotificationShelfController.setOnActivatedListener(mPresenter);
mRemoteInputManager.getController().addCallback(mNotificationShadeWindowController);
mNotificationActivityStarter =
@@ -1320,16 +1327,13 @@ public class StatusBar extends SystemUI implements DemoMode,
.setNotificationPresenter(mPresenter)
.setNotificationPanelViewController(mNotificationPanelViewController)
.build();
-
- ((NotificationListContainer) mStackScroller)
- .setNotificationActivityStarter(mNotificationActivityStarter);
-
+ mStackScroller.setNotificationActivityStarter(mNotificationActivityStarter);
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
mNotificationsController.initialize(
this,
mPresenter,
- (NotificationListContainer) mStackScroller,
+ mStackScrollerController.getNotificationListContainer(),
mNotificationActivityStarter,
mPresenter);
}
@@ -1386,8 +1390,9 @@ public class StatusBar extends SystemUI implements DemoMode,
}
private void inflateShelf() {
- mNotificationShelf = mSuperStatusBarViewFactory.getNotificationShelf(mStackScroller);
- mNotificationShelf.setOnClickListener(mGoToLockedShadeListener);
+ mNotificationShelfController = mSuperStatusBarViewFactory
+ .getNotificationShelfController(mStackScroller);
+ mNotificationShelfController.setOnClickListener(mGoToLockedShadeListener);
}
@Override
@@ -4049,7 +4054,7 @@ public class StatusBar extends SystemUI implements DemoMode,
protected IStatusBarService mBarService;
// all notifications
- protected ViewGroup mStackScroller;
+ protected NotificationStackScrollLayout mStackScroller;
private final NotificationGroupManager mGroupManager;
@@ -4085,8 +4090,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private final Optional<Recents> mRecentsOptional;
- protected NotificationShelf mNotificationShelf;
- protected EmptyShadeView mEmptyShadeView;
+ protected NotificationShelfController mNotificationShelfController;
private final Lazy<AssistManager> mAssistManagerLazy;
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 45f0c49a4fd4..f1715bef62d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -30,7 +30,6 @@ import android.service.vr.IVrStateCallbacks;
import android.util.Log;
import android.util.Slog;
import android.view.View;
-import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
import android.widget.TextView;
@@ -71,7 +70,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -133,7 +132,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
NotificationPanelViewController panel,
HeadsUpManagerPhone headsUp,
NotificationShadeWindowView statusBarWindow,
- ViewGroup stackScroller,
+ NotificationStackScrollLayoutController stackScrollerController,
DozeScrimController dozeScrimController,
ScrimController scrimController,
ActivityLaunchAnimator activityLaunchAnimator,
@@ -155,7 +154,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
mStatusBar = statusBar;
mShadeController = shadeController;
mCommandQueue = commandQueue;
- mAboveShelfObserver = new AboveShelfObserver(stackScroller);
+ mAboveShelfObserver = new AboveShelfObserver(stackScrollerController.getView());
mActivityLaunchAnimator = activityLaunchAnimator;
mAboveShelfObserver.setListener(statusBarWindow.findViewById(
R.id.notification_container_parent));
@@ -190,7 +189,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
remoteInputManager.getController().addCallback(
Dependency.get(NotificationShadeWindowController.class));
- NotificationListContainer notifListContainer = (NotificationListContainer) stackScroller;
initController.addPostInitTask(() -> {
NotificationEntryListener notificationEntryListener = new NotificationEntryListener() {
@Override
@@ -207,7 +205,8 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
}
};
- mViewHierarchyManager.setUpWithPresenter(this, notifListContainer);
+ mViewHierarchyManager.setUpWithPresenter(this,
+ stackScrollerController.getNotificationListContainer());
mEntryManager.setUpWithPresenter(this);
mEntryManager.addNotificationEntryListener(notificationEntryListener);
mEntryManager.addNotificationLifetimeExtender(mHeadsUpManager);
@@ -219,7 +218,8 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
mMediaManager.setUpWithPresenter(this);
mVisualStabilityManager.setUpWithPresenter(this);
mGutsManager.setUpWithPresenter(this,
- notifListContainer, mCheckSaveListener, mOnSettingsClickListener);
+ stackScrollerController.getNotificationListContainer(), mCheckSaveListener,
+ mOnSettingsClickListener);
// ForegroundServiceNotificationListener adds its listener in its constructor
// but we need to request it here in order for it to be instantiated.
// TODO: figure out how to do this correctly once Dependency.get() is gone.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index 72395e68ff07..ac69d9c32c93 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -244,9 +244,10 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks,
@Override
public boolean handleRemoteViewClick(View view, PendingIntent pendingIntent,
+ boolean appRequestedAuth,
NotificationRemoteInputManager.ClickHandler defaultHandler) {
final boolean isActivity = pendingIntent.isActivity();
- if (isActivity) {
+ if (isActivity || appRequestedAuth) {
mActionClickLogger.logWaitingToCloseKeyguard(pendingIntent);
final boolean afterKeyguardGone = mActivityIntentHelper.wouldLaunchResolverActivity(
pendingIntent.getIntent(), mLockscreenUserManager.getCurrentUserId());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioActivityObserver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioActivityObserver.java
index 87b3956060f3..bbab6253a4d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioActivityObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioActivityObserver.java
@@ -40,5 +40,9 @@ abstract class AudioActivityObserver {
mListener = listener;
}
+ abstract void start();
+
+ abstract void stop();
+
abstract Set<String> getActivePackages();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
index 8e4e12358836..e3eed35f0483 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
@@ -22,12 +22,12 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
import android.annotation.IntDef;
import android.annotation.UiThread;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.database.ContentObserver;
import android.graphics.PixelFormat;
import android.provider.Settings;
import android.text.TextUtils;
@@ -65,11 +65,13 @@ public class AudioRecordingDisclosureBar implements
// CtsSystemUiHostTestCases:TvMicrophoneCaptureIndicatorTest
private static final String LAYOUT_PARAMS_TITLE = "MicrophoneCaptureIndicator";
+ private static final String ENABLE_FLAG = "sysui_mic_disclosure_enable";
private static final String EXEMPT_PACKAGES_LIST = "sysui_mic_disclosure_exempt";
private static final String FORCED_PACKAGES_LIST = "sysui_mic_disclosure_forced";
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"STATE_"}, value = {
+ STATE_STOPPED,
STATE_NOT_SHOWN,
STATE_APPEARING,
STATE_SHOWN,
@@ -80,6 +82,7 @@ public class AudioRecordingDisclosureBar implements
})
public @interface State {}
+ private static final int STATE_STOPPED = -1;
private static final int STATE_NOT_SHOWN = 0;
private static final int STATE_APPEARING = 1;
private static final int STATE_SHOWN = 2;
@@ -90,10 +93,9 @@ public class AudioRecordingDisclosureBar implements
private static final int ANIMATION_DURATION = 600;
private static final int MAXIMIZED_DURATION = 3000;
- private static final int PULSE_BIT_DURATION = 1000;
- private static final float PULSE_SCALE = 1.25f;
private final Context mContext;
+ private boolean mIsEnabledInSettings;
private View mIndicatorView;
private View mIconTextsContainer;
@@ -104,13 +106,13 @@ public class AudioRecordingDisclosureBar implements
private TextView mTextView;
private boolean mIsLtr;
- @State private int mState = STATE_NOT_SHOWN;
+ @State private int mState = STATE_STOPPED;
/**
* Array of the observers that monitor different aspects of the system, such as AppOps and
* microphone foreground services
*/
- private final AudioActivityObserver[] mAudioActivityObservers;
+ private AudioActivityObserver[] mAudioActivityObservers;
/**
* Whether the indicator should expand and show the recording application's label.
* If disabled ({@code false}) the "minimized" ({@link #STATE_MINIMIZED}) indicator would appear
@@ -144,6 +146,7 @@ public class AudioRecordingDisclosureBar implements
public AudioRecordingDisclosureBar(Context context) {
mContext = context;
+ // Loading configs
mRevealRecordingPackages = mContext.getResources().getBoolean(
R.bool.audio_recording_disclosure_reveal_packages);
mExemptPackages = new ArraySet<>(
@@ -152,10 +155,52 @@ public class AudioRecordingDisclosureBar implements
mExemptPackages.addAll(Arrays.asList(getGlobalStringArray(EXEMPT_PACKAGES_LIST)));
mExemptPackages.removeAll(Arrays.asList(getGlobalStringArray(FORCED_PACKAGES_LIST)));
- mAudioActivityObservers = new AudioActivityObserver[]{
- new RecordAudioAppOpObserver(mContext, this),
- new MicrophoneForegroundServicesObserver(mContext, this),
- };
+ // Check setting, and start if enabled
+ mIsEnabledInSettings = checkIfEnabledInSettings();
+ registerSettingsObserver();
+ if (mIsEnabledInSettings) {
+ start();
+ }
+ }
+
+ @UiThread
+ private void start() {
+ if (mState != STATE_STOPPED) {
+ return;
+ }
+ mState = STATE_NOT_SHOWN;
+
+ if (mAudioActivityObservers == null) {
+ mAudioActivityObservers = new AudioActivityObserver[]{
+ new RecordAudioAppOpObserver(mContext, this),
+ new MicrophoneForegroundServicesObserver(mContext, this),
+ };
+ }
+
+ for (int i = mAudioActivityObservers.length - 1; i >= 0; i--) {
+ mAudioActivityObservers[i].start();
+ }
+ }
+
+ @UiThread
+ private void stop() {
+ if (mState == STATE_STOPPED) {
+ return;
+ }
+ mState = STATE_STOPPED;
+
+ for (int i = mAudioActivityObservers.length - 1; i >= 0; i--) {
+ mAudioActivityObservers[i].stop();
+ }
+
+ // Remove the view if shown.
+ if (mState != STATE_NOT_SHOWN) {
+ removeIndicatorView();
+ }
+
+ // Clean up the state.
+ mSessionNotifiedPackages.clear();
+ mPendingNotificationPackages.clear();
}
@UiThread
@@ -213,7 +258,6 @@ public class AudioRecordingDisclosureBar implements
@UiThread
private void hideIndicatorIfNeeded() {
- if (DEBUG) Log.d(TAG, "hideIndicatorIfNeeded");
// If not MINIMIZED, will check whether the indicator should be hidden when the indicator
// comes to the STATE_MINIMIZED eventually.
if (mState != STATE_MINIMIZED) return;
@@ -222,7 +266,6 @@ public class AudioRecordingDisclosureBar implements
for (int index = mAudioActivityObservers.length - 1; index >= 0; index--) {
for (String activePackage : mAudioActivityObservers[index].getActivePackages()) {
if (mExemptPackages.contains(activePackage)) continue;
- if (DEBUG) Log.d(TAG, " - there are still ongoing activities");
return;
}
}
@@ -235,7 +278,7 @@ public class AudioRecordingDisclosureBar implements
@UiThread
private void show(String packageName) {
if (DEBUG) {
- Log.d(TAG, "Showing indicator for " + packageName);
+ Log.d(TAG, "Showing indicator");
}
mIsLtr = mContext.getResources().getConfiguration().getLayoutDirection()
@@ -286,6 +329,10 @@ public class AudioRecordingDisclosureBar implements
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
+ if (mState == STATE_STOPPED) {
+ return;
+ }
+
// Remove the observer
mIndicatorView.getViewTreeObserver().removeOnGlobalLayoutListener(
this);
@@ -306,13 +353,16 @@ public class AudioRecordingDisclosureBar implements
@Override
public void onAnimationStart(Animator animation,
boolean isReverse) {
+ if (mState == STATE_STOPPED) {
+ return;
+ }
+
// Indicator is INVISIBLE at the moment, change it.
mIndicatorView.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animator animation) {
- startPulsatingAnimation();
if (mRevealRecordingPackages) {
onExpanded();
} else {
@@ -345,9 +395,6 @@ public class AudioRecordingDisclosureBar implements
assertRevealingRecordingPackages();
final String label = getApplicationLabel(packageName);
- if (DEBUG) {
- Log.d(TAG, "Expanding for " + packageName + " (" + label + ")...");
- }
mTextView.setText(mContext.getString(R.string.app_accessed_mic, label));
final AnimatorSet set = new AnimatorSet();
@@ -373,7 +420,6 @@ public class AudioRecordingDisclosureBar implements
private void minimize() {
assertRevealingRecordingPackages();
- if (DEBUG) Log.d(TAG, "Minimizing...");
final int targetOffset = (mIsLtr ? 1 : -1) * mTextsContainers.getWidth();
final AnimatorSet set = new AnimatorSet();
set.playTogether(
@@ -396,7 +442,9 @@ public class AudioRecordingDisclosureBar implements
@UiThread
private void hide() {
- if (DEBUG) Log.d(TAG, "Hiding...");
+ if (DEBUG) {
+ Log.d(TAG, "Hide indicator");
+ }
final int targetOffset = (mIsLtr ? 1 : -1) * (mIndicatorView.getWidth()
- (int) mIconTextsContainer.getTranslationX());
final AnimatorSet set = new AnimatorSet();
@@ -418,9 +466,12 @@ public class AudioRecordingDisclosureBar implements
@UiThread
private void onExpanded() {
+ if (mState == STATE_STOPPED) {
+ return;
+ }
+
assertRevealingRecordingPackages();
- if (DEBUG) Log.d(TAG, "Expanded");
mState = STATE_SHOWN;
mIndicatorView.postDelayed(this::minimize, MAXIMIZED_DURATION);
@@ -428,7 +479,10 @@ public class AudioRecordingDisclosureBar implements
@UiThread
private void onMinimized() {
- if (DEBUG) Log.d(TAG, "Minimized");
+ if (mState == STATE_STOPPED) {
+ return;
+ }
+
mState = STATE_MINIMIZED;
if (mRevealRecordingPackages) {
@@ -443,8 +497,21 @@ public class AudioRecordingDisclosureBar implements
@UiThread
private void onHidden() {
- if (DEBUG) Log.d(TAG, "Hidden");
+ if (mState == STATE_STOPPED) {
+ return;
+ }
+ removeIndicatorView();
+ mState = STATE_NOT_SHOWN;
+
+ // Check if anybody started recording while we were in STATE_DISAPPEARING
+ if (!mPendingNotificationPackages.isEmpty()) {
+ // There is a new application that started recording, tell the user about it.
+ show(mPendingNotificationPackages.poll());
+ }
+ }
+
+ private void removeIndicatorView() {
final WindowManager windowManager = (WindowManager) mContext.getSystemService(
Context.WINDOW_SERVICE);
windowManager.removeView(mIndicatorView);
@@ -456,28 +523,6 @@ public class AudioRecordingDisclosureBar implements
mTextsContainers = null;
mTextView = null;
mBgEnd = null;
-
- mState = STATE_NOT_SHOWN;
-
- // Check if anybody started recording while we were in STATE_DISAPPEARING
- if (!mPendingNotificationPackages.isEmpty()) {
- // There is a new application that started recording, tell the user about it.
- show(mPendingNotificationPackages.poll());
- }
- }
-
- @UiThread
- private void startPulsatingAnimation() {
- final View pulsatingView = mIconTextsContainer.findViewById(R.id.pulsating_circle);
- final ObjectAnimator animator =
- ObjectAnimator.ofPropertyValuesHolder(
- pulsatingView,
- PropertyValuesHolder.ofFloat(View.SCALE_X, PULSE_SCALE),
- PropertyValuesHolder.ofFloat(View.SCALE_Y, PULSE_SCALE));
- animator.setDuration(PULSE_BIT_DURATION);
- animator.setRepeatCount(ObjectAnimator.INFINITE);
- animator.setRepeatMode(ObjectAnimator.REVERSE);
- animator.start();
}
private String[] getGlobalStringArray(String setting) {
@@ -504,4 +549,33 @@ public class AudioRecordingDisclosureBar implements
DEBUG ? new RuntimeException("Should not be called") : null);
}
}
+
+ private boolean checkIfEnabledInSettings() {
+ // 0 = disabled, everything else = enabled. Enabled by default.
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ ENABLE_FLAG, 1) != 0;
+ }
+
+ private void registerSettingsObserver() {
+ final ContentObserver contentObserver = new ContentObserver(
+ mContext.getMainThreadHandler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ if (mIsEnabledInSettings == checkIfEnabledInSettings()) {
+ // Nothing changed as we know it - ignore.
+ return;
+ }
+
+ // Things changed: flip the flag.
+ mIsEnabledInSettings = !mIsEnabledInSettings;
+ if (mIsEnabledInSettings) {
+ start();
+ } else {
+ stop();
+ }
+ }
+ };
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(ENABLE_FLAG), false, contentObserver);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/MicrophoneForegroundServicesObserver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/MicrophoneForegroundServicesObserver.java
index 1ede88a26020..8caf95fb48f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/MicrophoneForegroundServicesObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/MicrophoneForegroundServicesObserver.java
@@ -30,7 +30,6 @@ import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -41,9 +40,8 @@ import java.util.Set;
*/
class MicrophoneForegroundServicesObserver extends AudioActivityObserver {
private static final String TAG = "MicrophoneForegroundServicesObserver";
- private static final boolean ENABLED = true;
- private final IActivityManager mActivityManager;
+ private IActivityManager mActivityManager;
/**
* A dictionary that maps PIDs to the package names. We only keep track of the PIDs that are
* "active" (those that are running FGS with FOREGROUND_SERVICE_TYPE_MICROPHONE flag).
@@ -60,7 +58,10 @@ class MicrophoneForegroundServicesObserver extends AudioActivityObserver {
MicrophoneForegroundServicesObserver(Context context,
OnAudioActivityStateChangeListener listener) {
super(context, listener);
+ }
+ @Override
+ void start() {
mActivityManager = ActivityManager.getService();
try {
mActivityManager.registerProcessObserver(mProcessObserver);
@@ -70,8 +71,19 @@ class MicrophoneForegroundServicesObserver extends AudioActivityObserver {
}
@Override
+ void stop() {
+ try {
+ mActivityManager.unregisterProcessObserver(mProcessObserver);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't unregister process observer", e);
+ }
+ mActivityManager = null;
+ mPackageToProcessCount.clear();
+ }
+
+ @Override
Set<String> getActivePackages() {
- return ENABLED ? mPackageToProcessCount.keySet() : Collections.emptySet();
+ return mPackageToProcessCount.keySet();
}
@UiThread
@@ -141,13 +153,12 @@ class MicrophoneForegroundServicesObserver extends AudioActivityObserver {
@UiThread
private void notifyPackageStateChanged(String packageName, boolean active) {
- if (active) {
- if (DEBUG) Log.d(TAG, "New microphone fgs detected, package=" + packageName);
- } else {
- if (DEBUG) Log.d(TAG, "Microphone fgs is gone, package=" + packageName);
+ if (DEBUG) {
+ Log.d(TAG, (active ? "New microphone fgs detected" : "Microphone fgs is gone")
+ + ", package=" + packageName);
}
- if (ENABLED) mListener.onAudioActivityStateChange(active, packageName);
+ mListener.onAudioActivityStateChange(active, packageName);
}
@UiThread
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/RecordAudioAppOpObserver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/RecordAudioAppOpObserver.java
index b5b1c2b3018a..9a2b4a93ac89 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/RecordAudioAppOpObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/RecordAudioAppOpObserver.java
@@ -42,14 +42,33 @@ class RecordAudioAppOpObserver extends AudioActivityObserver implements
RecordAudioAppOpObserver(Context context, OnAudioActivityStateChangeListener listener) {
super(context, listener);
+ }
+
+ @Override
+ void start() {
+ if (DEBUG) {
+ Log.d(TAG, "Start");
+ }
// Register AppOpsManager callback
- final AppOpsManager appOpsManager = (AppOpsManager) mContext.getSystemService(
- Context.APP_OPS_SERVICE);
- appOpsManager.startWatchingActive(
- new String[]{AppOpsManager.OPSTR_RECORD_AUDIO},
- mContext.getMainExecutor(),
- this);
+ mContext.getSystemService(AppOpsManager.class)
+ .startWatchingActive(
+ new String[]{AppOpsManager.OPSTR_RECORD_AUDIO},
+ mContext.getMainExecutor(),
+ this);
+ }
+
+ @Override
+ void stop() {
+ if (DEBUG) {
+ Log.d(TAG, "Stop");
+ }
+
+ // Unregister AppOpsManager callback
+ mContext.getSystemService(AppOpsManager.class).stopWatchingActive(this);
+
+ // Clean up state
+ mActiveAudioRecordingPackages.clear();
}
@UiThread
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java
index dce38c109930..fd6ba1a6af0e 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIRootComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java
@@ -19,11 +19,10 @@ package com.android.systemui.tv;
import com.android.systemui.dagger.DefaultComponentBinder;
import com.android.systemui.dagger.DependencyBinder;
import com.android.systemui.dagger.DependencyProvider;
+import com.android.systemui.dagger.GlobalRootComponent;
import com.android.systemui.dagger.SystemServicesModule;
import com.android.systemui.dagger.SystemUIBinder;
-import com.android.systemui.dagger.SystemUIDefaultModule;
import com.android.systemui.dagger.SystemUIModule;
-import com.android.systemui.dagger.SystemUIRootComponent;
import com.android.systemui.onehanded.dagger.OneHandedModule;
import javax.inject.Singleton;
@@ -42,14 +41,17 @@ import dagger.Component;
SystemServicesModule.class,
SystemUIBinder.class,
SystemUIModule.class,
- SystemUIDefaultModule.class,
+ TvSystemUIModule.class,
TvSystemUIBinder.class})
-public interface TvSystemUIRootComponent extends SystemUIRootComponent {
+public interface TvGlobalRootComponent extends GlobalRootComponent {
/**
* Component Builder interface. This allows to bind Context instance in the component
*/
@Component.Builder
- interface Builder extends SystemUIRootComponent.Builder {
- TvSystemUIRootComponent build();
+ interface Builder extends GlobalRootComponent.Builder {
+ TvGlobalRootComponent build();
}
+
+ @Override
+ TvSysUIComponent.Builder getSysUIComponent();
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java
new file mode 100644
index 000000000000..bc0cb51c64a3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java
@@ -0,0 +1,38 @@
+/*
+ * 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.tv;
+
+import com.android.systemui.dagger.SysUIComponent;
+import com.android.systemui.dagger.SysUISingleton;
+
+import dagger.Subcomponent;
+
+/**
+ * Dagger Subcomponent for Core SysUI.
+ */
+@SysUISingleton
+@Subcomponent(modules = {})
+public interface TvSysUIComponent extends SysUIComponent {
+
+ /**
+ * Builder for a SysUIComponent.
+ */
+ @Subcomponent.Builder
+ interface Builder extends SysUIComponent.Builder {
+ TvSysUIComponent build();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java
index be30a4a4c72e..9a44bf12a3ef 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java
@@ -16,7 +16,7 @@
package com.android.systemui.tv;
-import com.android.systemui.dagger.SystemUIRootComponent;
+import com.android.systemui.dagger.GlobalRootComponent;
import com.android.systemui.pip.tv.dagger.PipModule;
import dagger.Binds;
@@ -25,5 +25,5 @@ import dagger.Module;
@Module(includes = {PipModule.class})
interface TvSystemUIBinder {
@Binds
- SystemUIRootComponent bindSystemUIRootComponent(TvSystemUIRootComponent systemUIRootComponent);
+ GlobalRootComponent bindGlobalRootComponent(TvGlobalRootComponent globalRootComponent);
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIFactory.java
index 7d3ec678fd5f..c99ad23ab23d 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIFactory.java
@@ -19,16 +19,16 @@ package com.android.systemui.tv;
import android.content.Context;
import com.android.systemui.SystemUIFactory;
-import com.android.systemui.dagger.SystemUIRootComponent;
+import com.android.systemui.dagger.GlobalRootComponent;
/**
- * TV variant {@link SystemUIFactory}, that substitutes default {@link SystemUIRootComponent} for
- * {@link TvSystemUIRootComponent}
+ * TV variant {@link SystemUIFactory}, that substitutes default {@link GlobalRootComponent} for
+ * {@link TvGlobalRootComponent}
*/
public class TvSystemUIFactory extends SystemUIFactory {
@Override
- protected SystemUIRootComponent buildSystemUIRootComponent(Context context) {
- return DaggerTvSystemUIRootComponent.builder()
+ protected GlobalRootComponent buildGlobalRootComponent(Context context) {
+ return DaggerTvGlobalRootComponent.builder()
.context(context)
.build();
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
new file mode 100644
index 000000000000..3f7350639fd3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
@@ -0,0 +1,165 @@
+/*
+ * 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.tv;
+
+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 android.os.Handler;
+import android.os.PowerManager;
+
+import androidx.annotation.Nullable;
+
+import com.android.keyguard.KeyguardViewController;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dock.DockManager;
+import com.android.systemui.dock.DockManagerImpl;
+import com.android.systemui.doze.DozeHost;
+import com.android.systemui.plugins.qs.QSFactory;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.power.EnhancedEstimates;
+import com.android.systemui.power.EnhancedEstimatesImpl;
+import com.android.systemui.qs.dagger.QSModule;
+import com.android.systemui.qs.tileimpl.QSFactoryImpl;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsImplementation;
+import com.android.systemui.stackdivider.DividerModule;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+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.KeyguardEnvironmentImpl;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.ShadeControllerImpl;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BatteryControllerImpl;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.wmshell.WindowManagerShellModule;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import dagger.Binds;
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * A dagger module for injecting default implementations of components of System UI that may be
+ * overridden by the System UI implementation.
+ */
+@Module(includes = {
+ DividerModule.class,
+ QSModule.class,
+ WindowManagerShellModule.class
+ },
+ subcomponents = {
+ TvSysUIComponent.class
+ })
+public abstract class TvSystemUIModule {
+
+ @Singleton
+ @Provides
+ @Named(LEAK_REPORT_EMAIL_NAME)
+ @Nullable
+ static String provideLeakReportEmail() {
+ return null;
+ }
+
+ @Binds
+ abstract EnhancedEstimates bindEnhancedEstimates(EnhancedEstimatesImpl enhancedEstimates);
+
+ @Binds
+ abstract NotificationLockscreenUserManager bindNotificationLockscreenUserManager(
+ NotificationLockscreenUserManagerImpl notificationLockscreenUserManager);
+
+ @Provides
+ @Singleton
+ static BatteryController provideBatteryController(Context context,
+ EnhancedEstimates enhancedEstimates, PowerManager powerManager,
+ BroadcastDispatcher broadcastDispatcher, @Main Handler mainHandler,
+ @Background Handler bgHandler) {
+ BatteryController bC = new BatteryControllerImpl(context, enhancedEstimates, powerManager,
+ broadcastDispatcher, mainHandler, bgHandler);
+ bC.init();
+ return bC;
+ }
+
+ @Binds
+ @Singleton
+ abstract QSFactory bindQSFactory(QSFactoryImpl qsFactoryImpl);
+
+ @Binds
+ abstract DockManager bindDockManager(DockManagerImpl dockManager);
+
+ @Binds
+ abstract NotificationEntryManager.KeyguardEnvironment bindKeyguardEnvironment(
+ KeyguardEnvironmentImpl keyguardEnvironment);
+
+ @Binds
+ abstract ShadeController provideShadeController(ShadeControllerImpl shadeController);
+
+ @Singleton
+ @Provides
+ @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME)
+ static boolean provideAllowNotificationLongPress() {
+ return true;
+ }
+
+ @Singleton
+ @Provides
+ static HeadsUpManagerPhone provideHeadsUpManagerPhone(
+ Context context,
+ StatusBarStateController statusBarStateController,
+ KeyguardBypassController bypassController,
+ NotificationGroupManager groupManager,
+ ConfigurationController configurationController) {
+ return new HeadsUpManagerPhone(context, statusBarStateController, bypassController,
+ groupManager, configurationController);
+ }
+
+ @Binds
+ abstract HeadsUpManager bindHeadsUpManagerPhone(HeadsUpManagerPhone headsUpManagerPhone);
+
+ @Provides
+ @Singleton
+ static Recents provideRecents(Context context, RecentsImplementation recentsImplementation,
+ CommandQueue commandQueue) {
+ return new Recents(context, recentsImplementation, commandQueue);
+ }
+
+ @Binds
+ abstract DeviceProvisionedController bindDeviceProvisionedController(
+ DeviceProvisionedControllerImpl deviceProvisionedController);
+
+ @Binds
+ abstract KeyguardViewController bindKeyguardViewController(
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager);
+
+ @Binds
+ abstract DozeHost provideDozeHost(DozeServiceHost dozeServiceHost);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index 551b7b41212a..c82b39af4ab3 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -25,13 +25,11 @@ import android.view.View;
import com.android.keyguard.KeyguardMessageArea;
import com.android.keyguard.KeyguardSliceView;
-import com.android.systemui.dagger.SystemUIRootComponent;
import com.android.systemui.qs.QSFooterImpl;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QuickQSPanel;
import com.android.systemui.qs.QuickStatusBarHeader;
import com.android.systemui.qs.customize.QSCustomizer;
-import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import java.lang.reflect.InvocationTargetException;
@@ -42,8 +40,7 @@ import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
-import dagger.Module;
-import dagger.Provides;
+import dagger.BindsInstance;
import dagger.Subcomponent;
/**
@@ -54,24 +51,16 @@ import dagger.Subcomponent;
public class InjectionInflationController {
public static final String VIEW_CONTEXT = "view_context";
- private final ViewCreator mViewCreator;
private final ArrayMap<String, Method> mInjectionMap = new ArrayMap<>();
private final LayoutInflater.Factory2 mFactory = new InjectionFactory();
+ private final ViewInstanceCreator.Factory mViewInstanceCreatorFactory;
@Inject
- public InjectionInflationController(SystemUIRootComponent rootComponent) {
- mViewCreator = rootComponent.createViewCreator();
+ public InjectionInflationController(ViewInstanceCreator.Factory viewInstanceCreatorFactory) {
+ mViewInstanceCreatorFactory = viewInstanceCreatorFactory;
initInjectionMap();
}
- ArrayMap<String, Method> getInjectionMap() {
- return mInjectionMap;
- }
-
- ViewCreator getFragmentCreator() {
- return mViewCreator;
- }
-
/**
* Wraps a {@link LayoutInflater} to support creating dagger injected views.
* See docs/dagger.md for details.
@@ -92,25 +81,19 @@ public class InjectionInflationController {
}
/**
- * The subcomponent of dagger that holds all views that need injection.
+ * Subcomponent that actually creates injected views.
*/
@Subcomponent
- public interface ViewCreator {
- /**
- * Creates another subcomponent to actually generate the view.
- */
- ViewInstanceCreator createInstanceCreator(ViewAttributeProvider attributeProvider);
- }
-
- /**
- * Secondary sub-component that actually creates the views.
- *
- * Having two subcomponents lets us hide the complexity of providing the named context
- * and AttributeSet from the SystemUIRootComponent, instead we have one subcomponent that
- * creates a new ViewInstanceCreator any time we need to inflate a view.
- */
- @Subcomponent(modules = ViewAttributeProvider.class)
public interface ViewInstanceCreator {
+
+ /** Factory for creating a ViewInstanceCreator. */
+ @Subcomponent.Factory
+ interface Factory {
+ ViewInstanceCreator build(
+ @BindsInstance @Named(VIEW_CONTEXT) Context context,
+ @BindsInstance AttributeSet attributeSet);
+ }
+
/**
* Creates the QuickStatusBarHeader.
*/
@@ -126,11 +109,6 @@ public class InjectionInflationController {
NotificationStackScrollLayout createNotificationStackScrollLayout();
/**
- * Creates the Shelf.
- */
- NotificationShelf creatNotificationShelf();
-
- /**
* Creates the KeyguardSliceView.
*/
KeyguardSliceView createKeyguardSliceView();
@@ -156,36 +134,6 @@ public class InjectionInflationController {
QSCustomizer createQSCustomizer();
}
- /**
- * Module for providing view-specific constructor objects.
- */
- @Module
- public class ViewAttributeProvider {
- private final Context mContext;
- private final AttributeSet mAttrs;
-
- private ViewAttributeProvider(Context context, AttributeSet attrs) {
- mContext = context;
- mAttrs = attrs;
- }
-
- /**
- * Provides the view-themed context (as opposed to the global sysui application context).
- */
- @Provides
- @Named(VIEW_CONTEXT)
- public Context provideContext() {
- return mContext;
- }
-
- /**
- * Provides the AttributeSet for the current view being inflated.
- */
- @Provides
- public AttributeSet provideAttributeSet() {
- return mAttrs;
- }
- }
private class InjectionFactory implements LayoutInflater.Factory2 {
@@ -193,10 +141,9 @@ public class InjectionInflationController {
public View onCreateView(String name, Context context, AttributeSet attrs) {
Method creationMethod = mInjectionMap.get(name);
if (creationMethod != null) {
- ViewAttributeProvider provider = new ViewAttributeProvider(context, attrs);
try {
return (View) creationMethod.invoke(
- mViewCreator.createInstanceCreator(provider));
+ mViewInstanceCreatorFactory.build(context, attrs));
} catch (IllegalAccessException e) {
throw new InflateException("Could not inflate " + name, e);
} catch (InvocationTargetException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 3455ff47de8d..51ad30ebcac6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -150,6 +150,8 @@ public class VolumeDialogImpl implements VolumeDialog,
private boolean mShowing;
private boolean mShowA11yStream;
+ private final boolean mShowLowMediaVolumeIcon;
+
private int mActiveStream;
private int mPrevActiveStream;
private boolean mAutomute = VolumePrefs.DEFAULT_ENABLE_AUTOMUTE;
@@ -166,7 +168,7 @@ public class VolumeDialogImpl implements VolumeDialog,
public VolumeDialogImpl(Context context) {
mContext =
- new ContextThemeWrapper(context, R.style.qs_theme);
+ new ContextThemeWrapper(context, R.style.volume_dialog_theme);
mController = Dependency.get(VolumeDialogController.class);
mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
@@ -175,6 +177,8 @@ public class VolumeDialogImpl implements VolumeDialog,
mShowActiveStreamOnly = showActiveStreamOnly();
mHasSeenODICaptionsTooltip =
Prefs.getBoolean(context, Prefs.Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP, false);
+ mShowLowMediaVolumeIcon =
+ mContext.getResources().getBoolean(R.bool.config_showLowMediaVolumeIcon);
}
@Override
@@ -421,6 +425,7 @@ public class VolumeDialogImpl implements VolumeDialog,
row.dndIcon = row.view.findViewById(R.id.dnd_icon);
row.slider = row.view.findViewById(R.id.volume_row_slider);
row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row));
+ row.number = row.view.findViewById(R.id.volume_number);
row.anim = null;
@@ -935,6 +940,7 @@ public class VolumeDialogImpl implements VolumeDialog,
protected void onStateChangedH(State state) {
if (D.BUG) Log.d(TAG, "onStateChangedH() state: " + state.toString());
if (mState != null && state != null
+ && mState.ringerModeInternal != -1
&& mState.ringerModeInternal != state.ringerModeInternal
&& state.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE) {
mController.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK));
@@ -1024,19 +1030,28 @@ public class VolumeDialogImpl implements VolumeDialog,
final boolean iconEnabled = (mAutomute || ss.muteSupported) && !zenMuted;
row.icon.setEnabled(iconEnabled);
row.icon.setAlpha(iconEnabled ? 1 : 0.5f);
- final int iconRes =
- isRingVibrate ? R.drawable.ic_volume_ringer_vibrate
- : isRingSilent || zenMuted ? row.iconMuteRes
- : ss.routedToBluetooth
- ? isStreamMuted(ss) ? R.drawable.ic_volume_media_bt_mute
- : R.drawable.ic_volume_media_bt
- : isStreamMuted(ss) ? row.iconMuteRes : row.iconRes;
+ final int iconRes;
+ if (isRingVibrate) {
+ iconRes = R.drawable.ic_volume_ringer_vibrate;
+ } else if (isRingSilent || zenMuted) {
+ iconRes = row.iconMuteRes;
+ } else if (ss.routedToBluetooth) {
+ iconRes = isStreamMuted(ss) ? R.drawable.ic_volume_media_bt_mute
+ : R.drawable.ic_volume_media_bt;
+ } else if (isStreamMuted(ss)) {
+ iconRes = row.iconMuteRes;
+ } else {
+ iconRes = mShowLowMediaVolumeIcon && ss.level * 2 < (ss.levelMax + ss.levelMin)
+ ? R.drawable.ic_volume_media_low : row.iconRes;
+ }
+
row.icon.setImageResource(iconRes);
row.iconState =
iconRes == R.drawable.ic_volume_ringer_vibrate ? Events.ICON_STATE_VIBRATE
: (iconRes == R.drawable.ic_volume_media_bt_mute || iconRes == row.iconMuteRes)
? Events.ICON_STATE_MUTE
- : (iconRes == R.drawable.ic_volume_media_bt || iconRes == row.iconRes)
+ : (iconRes == R.drawable.ic_volume_media_bt || iconRes == row.iconRes
+ || iconRes == R.drawable.ic_volume_media_low)
? Events.ICON_STATE_UNMUTE
: Events.ICON_STATE_UNKNOWN;
if (iconEnabled) {
@@ -1090,6 +1105,7 @@ public class VolumeDialogImpl implements VolumeDialog,
final int vlevel = row.ss.muted && (!isRingStream && !zenMuted) ? 0
: row.ss.level;
updateVolumeRowSliderH(row, enableSlider, vlevel);
+ if (row.number != null) row.number.setText(Integer.toString(vlevel));
}
private boolean isStreamMuted(final StreamState streamState) {
@@ -1115,6 +1131,10 @@ public class VolumeDialogImpl implements VolumeDialog,
row.icon.setImageTintList(tint);
row.icon.setImageAlpha(alpha);
row.cachedTint = tint;
+ if (row.number != null) {
+ row.number.setTextColor(tint);
+ row.number.setAlpha(alpha);
+ }
}
private void updateVolumeRowSliderH(VolumeRow row, boolean enable, int vlevel) {
@@ -1346,7 +1366,7 @@ public class VolumeDialogImpl implements VolumeDialog,
private final class CustomDialog extends Dialog implements DialogInterface {
public CustomDialog(Context context) {
- super(context, R.style.qs_theme);
+ super(context, R.style.volume_dialog_theme);
}
@Override
@@ -1458,6 +1478,7 @@ public class VolumeDialogImpl implements VolumeDialog,
private TextView header;
private ImageButton icon;
private SeekBar slider;
+ private TextView number;
private int stream;
private StreamState ss;
private long userAttempt; // last user-driven slider change
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index 4c0762e4ea32..0d52e4fefd3e 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -79,7 +79,9 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
.thenReturn(mMockKeyguardSliceView);
InjectionInflationController inflationController = new InjectionInflationController(
- SystemUIFactory.getInstance().getRootComponent());
+ SystemUIFactory.getInstance()
+ .getRootComponent()
+ .createViewInstanceCreatorFactory());
LayoutInflater layoutInflater = inflationController
.injectable(LayoutInflater.from(getContext()));
layoutInflater.setPrivateFactory(new LayoutInflater.Factory2() {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
index e6c2ddcf7e65..aa4db3205d82 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
@@ -65,7 +65,9 @@ public class KeyguardPresentationTest extends SysuiTestCase {
allowTestableLooperAsMainThread();
InjectionInflationController inflationController = new InjectionInflationController(
- SystemUIFactory.getInstance().getRootComponent());
+ SystemUIFactory.getInstance()
+ .getRootComponent()
+ .createViewInstanceCreatorFactory());
mLayoutInflater = inflationController.injectable(LayoutInflater.from(mContext));
mLayoutInflater.setPrivateFactory(new LayoutInflater.Factory2() {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java
index bc3c3d995ce6..560d581c20e7 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java
@@ -51,7 +51,9 @@ public class KeyguardStatusViewTest extends SysuiTestCase {
allowTestableLooperAsMainThread();
mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
InjectionInflationController inflationController = new InjectionInflationController(
- SystemUIFactory.getInstance().getRootComponent());
+ SystemUIFactory.getInstance()
+ .getRootComponent()
+ .createViewInstanceCreatorFactory());
LayoutInflater layoutInflater = inflationController
.injectable(LayoutInflater.from(getContext()));
mKeyguardStatusView =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java
index fbc8e9d8de79..ac567e0ae67d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java
@@ -25,6 +25,7 @@ import android.content.Context;
import android.os.RemoteException;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
import android.view.Display;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IWindowMagnificationConnection;
@@ -47,6 +48,7 @@ import org.mockito.MockitoAnnotations;
*/
@SmallTest
@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
public class IWindowMagnificationConnectionTest extends SysuiTestCase {
private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY;
@@ -57,7 +59,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase {
@Mock
private IWindowMagnificationConnectionCallback mConnectionCallback;
@Mock
- private WindowMagnificationController mWindowMagnificationController;
+ private WindowMagnificationAnimationController mWindowMagnificationAnimationController;
@Mock
private ModeSwitchesController mModeSwitchesController;
private IWindowMagnificationConnection mIWindowMagnificationConnection;
@@ -74,7 +76,8 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase {
any(IWindowMagnificationConnection.class));
mWindowMagnification = new WindowMagnification(getContext(),
getContext().getMainThreadHandler(), mCommandQueue, mModeSwitchesController);
- mWindowMagnification.mWindowMagnificationController = mWindowMagnificationController;
+ mWindowMagnification.mWindowMagnificationAnimationController =
+ mWindowMagnificationAnimationController;
mWindowMagnification.requestWindowMagnificationConnection(true);
assertNotNull(mIWindowMagnificationConnection);
mIWindowMagnificationConnection.setConnectionCallback(mConnectionCallback);
@@ -86,7 +89,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase {
Float.NaN);
waitForIdleSync();
- verify(mWindowMagnificationController).enableWindowMagnification(3.0f, Float.NaN,
+ verify(mWindowMagnificationAnimationController).enableWindowMagnification(3.0f, Float.NaN,
Float.NaN);
}
@@ -99,7 +102,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase {
mIWindowMagnificationConnection.disableWindowMagnification(TEST_DISPLAY);
waitForIdleSync();
- verify(mWindowMagnificationController).deleteWindowMagnification();
+ verify(mWindowMagnificationAnimationController).deleteWindowMagnification();
}
@Test
@@ -107,7 +110,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase {
mIWindowMagnificationConnection.setScale(TEST_DISPLAY, 3.0f);
waitForIdleSync();
- verify(mWindowMagnificationController).setScale(3.0f);
+ verify(mWindowMagnificationAnimationController).setScale(3.0f);
}
@Test
@@ -115,7 +118,7 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase {
mIWindowMagnificationConnection.moveWindowMagnifier(TEST_DISPLAY, 100f, 200f);
waitForIdleSync();
- verify(mWindowMagnificationController).moveWindowMagnifier(100f, 200f);
+ verify(mWindowMagnificationAnimationController).moveWindowMagnifier(100f, 200f);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
new file mode 100644
index 000000000000..b7c198e53cfa
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2020 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.accessibility;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.animation.ValueAnimator;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.testing.AndroidTestingRunner;
+import android.view.SurfaceControl;
+import android.view.animation.AccelerateInterpolator;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+
+import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+
+@MediumTest
+@RunWith(AndroidTestingRunner.class)
+public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
+
+ private static final float DEFAULT_SCALE = 3.0f;
+ private static final float DEFAULT_CENTER_X = 400.0f;
+ private static final float DEFAULT_CENTER_Y = 500.0f;
+ // The duration couldn't too short, otherwise the ValueAnimator won't work in expectation.
+ private static final long ANIMATION_DURATION_MS = 200;
+
+ private AtomicReference<Float> mCurrentScale = new AtomicReference<>((float) 0);
+ private AtomicReference<Float> mCurrentCenterX = new AtomicReference<>((float) 0);
+ private AtomicReference<Float> mCurrentCenterY = new AtomicReference<>((float) 0);
+ private ArgumentCaptor<Float> mScaleCaptor = ArgumentCaptor.forClass(Float.class);
+ private ArgumentCaptor<Float> mCenterXCaptor = ArgumentCaptor.forClass(Float.class);
+ private ArgumentCaptor<Float> mCenterYCaptor = ArgumentCaptor.forClass(Float.class);
+
+ @Mock
+ Handler mHandler;
+ @Mock
+ SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
+ @Mock
+ WindowMagnifierCallback mWindowMagnifierCallback;
+
+ private SpyWindowMagnificationController mController;
+ private WindowMagnificationController mSpyController;
+ private WindowMagnificationAnimationController mWindowMagnificationAnimationController;
+ private Instrumentation mInstrumentation;
+ private long mWaitingAnimationPeriod;
+ private long mWaitIntermediateAnimationPeriod;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ mWaitingAnimationPeriod = ANIMATION_DURATION_MS + 50;
+ mWaitIntermediateAnimationPeriod = ANIMATION_DURATION_MS / 2;
+ mController = new SpyWindowMagnificationController(mContext, mHandler,
+ mSfVsyncFrameProvider, null, new SurfaceControl.Transaction(),
+ mWindowMagnifierCallback);
+ mSpyController = mController.getSpyController();
+ mWindowMagnificationAnimationController = new WindowMagnificationAnimationController(
+ mContext, mController, newValueAnimator());
+ }
+
+ @Test
+ public void enableWindowMagnification_disabled_expectedStartAndEndValues() {
+ enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod);
+
+ verify(mSpyController, atLeast(2)).enableWindowMagnification(
+ mScaleCaptor.capture(),
+ mCenterXCaptor.capture(), mCenterYCaptor.capture());
+ verifyStartValue(mScaleCaptor, 1.0f);
+ verifyStartValue(mCenterXCaptor, DEFAULT_CENTER_X);
+ verifyStartValue(mCenterYCaptor, DEFAULT_CENTER_Y);
+ verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X, DEFAULT_CENTER_Y);
+ }
+
+ @Test
+ public void enableWindowMagnification_enabling_expectedStartAndEndValues() {
+ enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod);
+ final float targetScale = DEFAULT_SCALE + 1.0f;
+ final float targetCenterX = DEFAULT_CENTER_X + 100;
+ final float targetCenterY = DEFAULT_CENTER_Y + 100;
+
+ mInstrumentation.runOnMainSync(() -> {
+ Mockito.reset(mSpyController);
+ mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
+ targetCenterX, targetCenterY);
+ mCurrentScale.set(mController.getScale());
+ mCurrentCenterX.set(mController.getCenterX());
+ mCurrentCenterY.set(mController.getCenterY());
+ });
+
+ SystemClock.sleep(mWaitingAnimationPeriod);
+
+ verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(),
+ mCenterXCaptor.capture(), mCenterYCaptor.capture());
+ verifyStartValue(mScaleCaptor, mCurrentScale.get());
+ verifyStartValue(mCenterXCaptor, mCurrentCenterX.get());
+ verifyStartValue(mCenterYCaptor, mCurrentCenterY.get());
+ verifyFinalSpec(targetScale, targetCenterX, targetCenterY);
+ }
+
+ @Test
+ public void enableWindowMagnification_disabling_expectedStartAndEndValues() {
+ enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod);
+ deleteWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod);
+ final float targetScale = DEFAULT_SCALE + 1.0f;
+ final float targetCenterX = DEFAULT_CENTER_X + 100;
+ final float targetCenterY = DEFAULT_CENTER_Y + 100;
+
+ mInstrumentation.runOnMainSync(
+ () -> {
+ Mockito.reset(mSpyController);
+ mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
+ targetCenterX, targetCenterY);
+ mCurrentScale.set(mController.getScale());
+ mCurrentCenterX.set(mController.getCenterX());
+ mCurrentCenterY.set(mController.getCenterY());
+ });
+ SystemClock.sleep(mWaitingAnimationPeriod);
+
+ verify(mSpyController, atLeast(2)).enableWindowMagnification(
+ mScaleCaptor.capture(),
+ mCenterXCaptor.capture(), mCenterYCaptor.capture());
+ //Animating in reverse, so we only check if the start values are greater than current.
+ assertTrue(mScaleCaptor.getAllValues().get(0) > mCurrentScale.get());
+ assertEquals(targetScale, mScaleCaptor.getValue(), 0f);
+ assertTrue(mCenterXCaptor.getAllValues().get(0) > mCurrentCenterX.get());
+ assertEquals(targetCenterX, mCenterXCaptor.getValue(), 0f);
+ assertTrue(mCenterYCaptor.getAllValues().get(0) > mCurrentCenterY.get());
+ assertEquals(targetCenterY, mCenterYCaptor.getValue(), 0f);
+ verifyFinalSpec(targetScale, targetCenterX, targetCenterY);
+ }
+
+ @Test
+ public void enableWindowMagnificationWithSameScale_doNothing() {
+ enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod);
+
+ enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod);
+
+ verify(mSpyController, never()).enableWindowMagnification(anyFloat(), anyFloat(),
+ anyFloat());
+ }
+
+ @Test
+ public void setScale_enabled_expectedScale() {
+ enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod);
+
+ mInstrumentation.runOnMainSync(
+ () -> mWindowMagnificationAnimationController.setScale(DEFAULT_SCALE + 1));
+
+ verify(mSpyController).setScale(DEFAULT_SCALE + 1);
+ verifyFinalSpec(DEFAULT_SCALE + 1, DEFAULT_CENTER_X, DEFAULT_CENTER_Y);
+ }
+
+ @Test
+ public void deleteWindowMagnification_enabled_expectedStartAndEndValues() {
+ enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod);
+
+ deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod);
+
+ verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(),
+ mCenterXCaptor.capture(), mCenterYCaptor.capture());
+ verify(mSpyController).deleteWindowMagnification();
+ verifyStartValue(mScaleCaptor, DEFAULT_SCALE);
+ verifyStartValue(mCenterXCaptor, Float.NaN);
+ verifyStartValue(mCenterYCaptor, Float.NaN);
+ verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);
+ }
+
+ @Test
+ public void deleteWindowMagnification_disabled_doNothing() {
+ deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod);
+
+ Mockito.verifyNoMoreInteractions(mSpyController);
+ }
+
+ @Test
+ public void deleteWindowMagnification_enabling_checkStartAndEndValues() {
+ enableWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod);
+
+ //It just reverse the animation, so we don't need to wait the whole duration.
+ mInstrumentation.runOnMainSync(
+ () -> {
+ Mockito.reset(mSpyController);
+ mWindowMagnificationAnimationController.deleteWindowMagnification();
+ mCurrentScale.set(mController.getScale());
+ mCurrentCenterX.set(mController.getCenterX());
+ mCurrentCenterY.set(mController.getCenterY());
+ });
+ SystemClock.sleep(mWaitingAnimationPeriod);
+
+ verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(),
+ mCenterXCaptor.capture(), mCenterYCaptor.capture());
+ verify(mSpyController).deleteWindowMagnification();
+
+ //The animation is in verse, so we only check the start values should no be greater than
+ // the current one.
+ assertTrue(mScaleCaptor.getAllValues().get(0) <= mCurrentScale.get());
+ assertEquals(1.0f, mScaleCaptor.getValue(), 0f);
+ verifyStartValue(mCenterXCaptor, Float.NaN);
+ verifyStartValue(mCenterYCaptor, Float.NaN);
+ verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);
+ }
+
+ @Test
+ public void deleteWindowMagnification_disabling_checkStartAndValues() {
+ enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod);
+ deleteWindowMagnificationAndWaitAnimating(mWaitIntermediateAnimationPeriod);
+
+ deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod);
+
+ verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(),
+ mCenterXCaptor.capture(), mCenterYCaptor.capture());
+ verify(mSpyController).deleteWindowMagnification();
+ assertEquals(1.0f, mScaleCaptor.getValue(), 0f);
+ verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);
+ }
+
+ @Test
+ public void moveWindowMagnifier_enabled() {
+ enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod);
+
+ mInstrumentation.runOnMainSync(
+ () -> mWindowMagnificationAnimationController.moveWindowMagnifier(100f, 200f));
+
+ verify(mSpyController).moveWindowMagnifier(100f, 200f);
+ verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X + 100f, DEFAULT_CENTER_Y + 100f);
+ }
+
+ @Test
+ public void onConfigurationChanged_passThrough() {
+ mWindowMagnificationAnimationController.onConfigurationChanged(100);
+
+ verify(mSpyController).onConfigurationChanged(100);
+ }
+ private void verifyFinalSpec(float expectedScale, float expectedCenterX,
+ float expectedCenterY) {
+ assertEquals(expectedScale, mController.getScale(), 0f);
+ assertEquals(expectedCenterX, mController.getCenterX(), 0f);
+ assertEquals(expectedCenterY, mController.getCenterY(), 0f);
+ }
+
+ private void enableWindowMagnificationAndWaitAnimating(long duration) {
+ mInstrumentation.runOnMainSync(
+ () -> {
+ Mockito.reset(mSpyController);
+ mWindowMagnificationAnimationController.enableWindowMagnification(DEFAULT_SCALE,
+ DEFAULT_CENTER_X, DEFAULT_CENTER_Y);
+ });
+ SystemClock.sleep(duration);
+ }
+
+ private void deleteWindowMagnificationAndWaitAnimating(long duration) {
+ mInstrumentation.runOnMainSync(
+ () -> {
+ resetMockObjects();
+ mWindowMagnificationAnimationController.deleteWindowMagnification();
+ });
+ SystemClock.sleep(duration);
+ }
+
+ private void verifyStartValue(ArgumentCaptor<Float> captor, float startValue) {
+ assertEquals(startValue, captor.getAllValues().get(0), 0f);
+ }
+
+ private void resetMockObjects() {
+ Mockito.reset(mSpyController);
+ }
+
+ /**
+ * It observes the methods in {@link WindowMagnificationController} since we couldn't spy it
+ * directly.
+ */
+ private static class SpyWindowMagnificationController extends WindowMagnificationController {
+ private WindowMagnificationController mSpyController;
+
+ SpyWindowMagnificationController(Context context, Handler handler,
+ SfVsyncFrameCallbackProvider sfVsyncFrameProvider,
+ MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction,
+ WindowMagnifierCallback callback) {
+ super(context, handler, sfVsyncFrameProvider, mirrorWindowControl, transaction,
+ callback);
+ mSpyController = Mockito.mock(WindowMagnificationController.class);
+ }
+
+ WindowMagnificationController getSpyController() {
+ return mSpyController;
+ }
+
+ @Override
+ void enableWindowMagnification(float scale, float centerX, float centerY) {
+ super.enableWindowMagnification(scale, centerX, centerY);
+ mSpyController.enableWindowMagnification(scale, centerX, centerY);
+ }
+
+ @Override
+ void deleteWindowMagnification() {
+ super.deleteWindowMagnification();
+ mSpyController.deleteWindowMagnification();
+ }
+
+ @Override
+ void moveWindowMagnifier(float offsetX, float offsetY) {
+ super.moveWindowMagnifier(offsetX, offsetX);
+ mSpyController.moveWindowMagnifier(offsetX, offsetY);
+ }
+
+ @Override
+ void setScale(float scale) {
+ super.setScale(scale);
+ mSpyController.setScale(scale);
+ }
+
+ @Override
+ void onConfigurationChanged(int configDiff) {
+ super.onConfigurationChanged(configDiff);
+ mSpyController.onConfigurationChanged(configDiff);
+ }
+
+ }
+
+ private static ValueAnimator newValueAnimator() {
+ final ValueAnimator valueAnimator = new ValueAnimator();
+ valueAnimator.setDuration(ANIMATION_DURATION_MS);
+ valueAnimator.setInterpolator(new AccelerateInterpolator(2.5f));
+ valueAnimator.setFloatValues(0.0f, 1.0f);
+ return valueAnimator;
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
index 2007fbb8fc6c..f1f394e70689 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -18,6 +18,7 @@ package com.android.systemui.accessibility;
import static android.view.Choreographer.FrameCallback;
+import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeastOnce;
@@ -26,8 +27,12 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Instrumentation;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.os.Handler;
import android.testing.AndroidTestingRunner;
+import android.view.Display;
+import android.view.Surface;
import android.view.SurfaceControl;
import androidx.test.InstrumentationRegistry;
@@ -41,6 +46,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@SmallTest
@@ -57,12 +63,14 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
WindowMagnifierCallback mWindowMagnifierCallback;
@Mock
SurfaceControl.Transaction mTransaction;
+ private Context mContext;
private WindowMagnificationController mWindowMagnificationController;
private Instrumentation mInstrumentation;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ mContext = Mockito.spy(getContext());
mInstrumentation = InstrumentationRegistry.getInstrumentation();
doAnswer(invocation -> {
FrameCallback callback = invocation.getArgument(0);
@@ -73,8 +81,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
when(mTransaction.remove(any())).thenReturn(mTransaction);
when(mTransaction.setGeometry(any(), any(), any(),
anyInt())).thenReturn(mTransaction);
-
- mWindowMagnificationController = new WindowMagnificationController(getContext(),
+ mWindowMagnificationController = new WindowMagnificationController(mContext,
mHandler, mSfVsyncFrameProvider,
mMirrorWindowControl, mTransaction, mWindowMagnifierCallback);
verify(mMirrorWindowControl).setWindowDelegate(
@@ -83,9 +90,8 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
@After
public void tearDown() {
- mInstrumentation.runOnMainSync(() -> {
- mWindowMagnificationController.deleteWindowMagnification();
- });
+ mInstrumentation.runOnMainSync(
+ () -> mWindowMagnificationController.deleteWindowMagnification());
}
@Test
@@ -121,4 +127,27 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
verify(mSfVsyncFrameProvider, atLeastOnce()).postFrameCallback(any());
}
+
+ @Test
+ public void setScale_enabled_expectedValue() {
+ mInstrumentation.runOnMainSync(
+ () -> mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ Float.NaN));
+
+ mInstrumentation.runOnMainSync(() -> mWindowMagnificationController.setScale(3.0f));
+
+ assertEquals(3.0f, mWindowMagnificationController.getScale(), 0);
+ }
+
+ @Test
+ public void onConfigurationChanged_disabled_withoutException() {
+ Display display = Mockito.spy(mContext.getDisplay());
+ when(display.getRotation()).thenReturn(Surface.ROTATION_90);
+ when(mContext.getDisplay()).thenReturn(display);
+
+ mInstrumentation.runOnMainSync(() -> {
+ mWindowMagnificationController.onConfigurationChanged(ActivityInfo.CONFIG_DENSITY);
+ mWindowMagnificationController.onConfigurationChanged(ActivityInfo.CONFIG_ORIENTATION);
+ });
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
index 41360130ac65..936558bca2d2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
@@ -26,6 +26,7 @@ import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.RemoteException;
import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
import android.view.Display;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IWindowMagnificationConnection;
@@ -45,6 +46,7 @@ import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
public class WindowMagnificationTest extends SysuiTestCase {
@Mock
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
index 4fdc06e64e2c..8f082c15df36 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -27,6 +27,9 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -34,6 +37,8 @@ import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
import android.content.pm.PackageManager;
+import android.media.AudioManager;
+import android.media.AudioRecordingConfiguration;
import android.os.Looper;
import android.os.UserHandle;
import android.testing.AndroidTestingRunner;
@@ -47,9 +52,11 @@ import com.android.systemui.dump.DumpManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Collections;
import java.util.List;
@SmallTest
@@ -73,6 +80,12 @@ public class AppOpsControllerTest extends SysuiTestCase {
private PermissionFlagsCache mFlagsCache;
@Mock
private PackageManager mPackageManager;
+ @Mock(stubOnly = true)
+ private AudioManager mAudioManager;
+ @Mock(stubOnly = true)
+ private AudioManager.AudioRecordingCallback mRecordingCallback;
+ @Mock(stubOnly = true)
+ private AudioRecordingConfiguration mPausedMockRecording;
private AppOpsControllerImpl mController;
private TestableLooper mTestableLooper;
@@ -94,11 +107,20 @@ public class AppOpsControllerTest extends SysuiTestCase {
when(mFlagsCache.getPermissionFlags(anyString(), anyString(),
eq(TEST_UID_NON_USER_SENSITIVE))).thenReturn(0);
+ doAnswer((invocation) -> mRecordingCallback = invocation.getArgument(0))
+ .when(mAudioManager).registerAudioRecordingCallback(any(), any());
+ when(mPausedMockRecording.getClientUid()).thenReturn(TEST_UID);
+ when(mPausedMockRecording.isClientSilenced()).thenReturn(true);
+
+ when(mAudioManager.getActiveRecordingConfigurations())
+ .thenReturn(List.of(mPausedMockRecording));
+
mController = new AppOpsControllerImpl(
mContext,
mTestableLooper.getLooper(),
mDumpManager,
- mFlagsCache
+ mFlagsCache,
+ mAudioManager
);
}
@@ -363,6 +385,89 @@ public class AppOpsControllerTest extends SysuiTestCase {
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
}
+ @Test
+ public void testPausedRecordingIsRetrievedOnCreation() {
+ mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
+ mTestableLooper.processAllMessages();
+
+ mController.onOpActiveChanged(
+ AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
+ mTestableLooper.processAllMessages();
+
+ verify(mCallback, never())
+ .onActiveStateChanged(anyInt(), anyInt(), anyString(), anyBoolean());
+ }
+
+ @Test
+ public void testPausedRecordingFilteredOut() {
+ mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
+ mTestableLooper.processAllMessages();
+
+ mController.onOpActiveChanged(
+ AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
+ mTestableLooper.processAllMessages();
+
+ assertTrue(mController.getActiveAppOps().isEmpty());
+ }
+
+ @Test
+ public void testOnlyRecordAudioPaused() {
+ mController.addCallback(new int[]{
+ AppOpsManager.OP_RECORD_AUDIO,
+ AppOpsManager.OP_CAMERA
+ }, mCallback);
+ mTestableLooper.processAllMessages();
+
+ mController.onOpActiveChanged(
+ AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, true);
+ mTestableLooper.processAllMessages();
+
+ verify(mCallback).onActiveStateChanged(
+ AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, true);
+ List<AppOpItem> list = mController.getActiveAppOps();
+
+ assertEquals(1, list.size());
+ assertEquals(AppOpsManager.OP_CAMERA, list.get(0).getCode());
+ }
+
+ @Test
+ public void testUnpausedRecordingSentActive() {
+ mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
+ mTestableLooper.processAllMessages();
+ mController.onOpActiveChanged(
+ AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
+
+ mTestableLooper.processAllMessages();
+ mRecordingCallback.onRecordingConfigChanged(Collections.emptyList());
+
+ mTestableLooper.processAllMessages();
+
+ verify(mCallback).onActiveStateChanged(
+ AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
+ }
+
+ @Test
+ public void testAudioPausedSentInactive() {
+ mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
+ mTestableLooper.processAllMessages();
+ mController.onOpActiveChanged(
+ AppOpsManager.OP_RECORD_AUDIO, TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
+ mTestableLooper.processAllMessages();
+
+ AudioRecordingConfiguration mockARC = mock(AudioRecordingConfiguration.class);
+ when(mockARC.getClientUid()).thenReturn(TEST_UID_OTHER);
+ when(mockARC.isClientSilenced()).thenReturn(true);
+
+ mRecordingCallback.onRecordingConfigChanged(List.of(mockARC));
+ mTestableLooper.processAllMessages();
+
+ InOrder inOrder = inOrder(mCallback);
+ inOrder.verify(mCallback).onActiveStateChanged(
+ AppOpsManager.OP_RECORD_AUDIO, TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
+ inOrder.verify(mCallback).onActiveStateChanged(
+ AppOpsManager.OP_RECORD_AUDIO, TEST_UID_OTHER, TEST_PACKAGE_NAME, false);
+ }
+
private class TestHandler extends AppOpsControllerImpl.H {
TestHandler(Looper looper) {
mController.super(looper);
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 b7589534a770..5c86fcb6b008 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -60,6 +60,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dump.DumpManager;
@@ -70,7 +71,9 @@ import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
+import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.RankingBuilder;
+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;
@@ -79,8 +82,10 @@ import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.LockscreenLockIconController;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
@@ -90,6 +95,7 @@ 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.FloatingContentCoordinator;
+import com.android.systemui.util.InjectionInflationController;
import com.google.common.collect.ImmutableList;
@@ -174,6 +180,8 @@ public class BubbleControllerTest extends SysuiTestCase {
@Mock
private ShadeController mShadeController;
@Mock
+ private NotificationShelfComponent mNotificationShelfComponent;
+ @Mock
private NotifPipeline mNotifPipeline;
@Mock
private FeatureFlags mFeatureFlagsOldPipeline;
@@ -185,11 +193,14 @@ public class BubbleControllerTest extends SysuiTestCase {
private IStatusBarService mStatusBarService;
@Mock
private LauncherApps mLauncherApps;
+ @Mock private LockscreenLockIconController mLockIconController;
private BubbleData mBubbleData;
private TestableLooper mTestableLooper;
+ private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -199,6 +210,24 @@ public class BubbleControllerTest extends SysuiTestCase {
mContext.addMockSystemService(FaceManager.class, mFaceManager);
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
+ mSuperStatusBarViewFactory = new SuperStatusBarViewFactory(mContext,
+ new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()
+ .createViewInstanceCreatorFactory()),
+ new NotificationShelfComponent.Builder() {
+ @Override
+ public NotificationShelfComponent.Builder notificationShelf(
+ NotificationShelf view) {
+ return this;
+ }
+
+ @Override
+ public NotificationShelfComponent build() {
+ return mNotificationShelfComponent;
+ }
+ },
+ mLockIconController);
+
+ // Bubbles get added to status bar window view
mNotificationShadeWindowController = new NotificationShadeWindowController(mContext,
mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
mConfigurationController, mKeyguardViewMediator, mKeyguardBypassController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
index 43bf19111049..196aa65bd28f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
@@ -58,6 +58,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.internal.statusbar.IStatusBarService;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dump.DumpManager;
@@ -66,7 +67,9 @@ import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.RankingBuilder;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
@@ -75,7 +78,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
-import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
+import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.LockscreenLockIconController;
@@ -88,6 +91,7 @@ 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.FloatingContentCoordinator;
+import com.android.systemui.util.InjectionInflationController;
import org.junit.Before;
import org.junit.Ignore;
@@ -168,7 +172,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
@Mock
private ShadeController mShadeController;
@Mock
- private NotificationRowComponent mNotificationRowComponent;
+ private NotificationShelfComponent mNotificationShelfComponent;
@Mock
private NotifPipeline mNotifPipeline;
@Mock
@@ -185,6 +189,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
private BubbleData mBubbleData;
private TestableLooper mTestableLooper;
+ private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
@Before
public void setUp() throws Exception {
@@ -195,6 +200,23 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
mContext.addMockSystemService(FaceManager.class, mFaceManager);
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
+ mSuperStatusBarViewFactory = new SuperStatusBarViewFactory(mContext,
+ new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()
+ .createViewInstanceCreatorFactory()),
+ new NotificationShelfComponent.Builder() {
+ @Override
+ public NotificationShelfComponent.Builder notificationShelf(
+ NotificationShelf view) {
+ return this;
+ }
+
+ @Override
+ public NotificationShelfComponent build() {
+ return mNotificationShelfComponent;
+ }
+ },
+ mLockIconController);
+
// Bubbles get added to status bar window view
mNotificationShadeWindowController = new NotificationShadeWindowController(mContext,
mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index f70fb4f55a8d..d1f505baa9e3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -254,16 +254,12 @@ public class KeyguardSliceProviderTest extends SysuiTestCase {
int mCleanDateFormatInvokations;
private int mCounter;
- Uri getUri() {
- return mSliceUri;
- }
+ TestableKeyguardSliceProvider() {
+ super();
- @Override
- protected void inject() {
mAlarmManager = KeyguardSliceProviderTest.this.mAlarmManager;
mContentResolver = KeyguardSliceProviderTest.this.mContentResolver;
mZenModeController = KeyguardSliceProviderTest.this.mZenModeController;
- mMediaWakeLock = KeyguardSliceProviderTest.this.mMediaWakeLock;
mDozeParameters = KeyguardSliceProviderTest.this.mDozeParameters;
mNextAlarmController = KeyguardSliceProviderTest.this.mNextAlarmController;
mStatusBarStateController = KeyguardSliceProviderTest.this.mStatusBarStateController;
@@ -272,6 +268,17 @@ public class KeyguardSliceProviderTest extends SysuiTestCase {
}
@Override
+ public boolean onCreateSliceProvider() {
+ boolean result = super.onCreateSliceProvider();
+ mMediaWakeLock = KeyguardSliceProviderTest.this.mMediaWakeLock;
+ return result;
+ }
+
+ Uri getUri() {
+ return mSliceUri;
+ }
+
+ @Override
protected boolean isDndOn() {
return mIsZenMode;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 90e9ef4e9c56..98a6ced91af6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -46,6 +46,7 @@ import com.android.systemui.statusbar.phone.NavigationModeController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.DeviceConfigProxyFake;
+import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
@@ -71,6 +72,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
private @Mock PowerManager mPowerManager;
private @Mock TrustManager mTrustManager;
private @Mock NavigationModeController mNavigationModeController;
+ private @Mock InjectionInflationController mInjectionInflationController;
private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake();
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@@ -88,7 +90,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
mContext, mFalsingManager, mLockPatternUtils, mBroadcastDispatcher,
() -> mStatusBarKeyguardViewManager,
mDismissCallbackRegistry, mUpdateMonitor, mDumpManager, mUiBgExecutor,
- mPowerManager, mTrustManager, mDeviceConfig, mNavigationModeController);
+ mPowerManager, mTrustManager, mDeviceConfig, mNavigationModeController,
+ mInjectionInflationController);
mViewMediator.start();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java
index 492b33e3c4a6..2e794a40d238 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java
@@ -83,8 +83,8 @@ public class MediaDataCombineLatestTest extends SysuiTestCase {
mManager.addListener(mListener);
mMediaData = new MediaData(USER_ID, true, BG_COLOR, APP, null, ARTIST, TITLE, null,
- new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null, true, null, false,
- KEY, false);
+ new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null, true, null, true,
+ false, KEY, false);
mDeviceData = new MediaDeviceData(true, null, DEVICE_NAME);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
index 3789e6ef1f65..a4ebe1ff2a4e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
@@ -13,6 +13,7 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dump.DumpManager
+import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.SbnBuilder
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.eq
@@ -58,6 +59,7 @@ class MediaDataManagerTest : SysuiTestCase() {
@Mock lateinit var mediaTimeoutListener: MediaTimeoutListener
@Mock lateinit var mediaResumeListener: MediaResumeListener
@Mock lateinit var pendingIntent: PendingIntent
+ @Mock lateinit var activityStarter: ActivityStarter
@JvmField @Rule val mockito = MockitoJUnit.rule()
lateinit var mediaDataManager: MediaDataManager
lateinit var mediaNotification: StatusBarNotification
@@ -68,8 +70,8 @@ class MediaDataManagerTest : SysuiTestCase() {
backgroundExecutor = FakeExecutor(FakeSystemClock())
mediaDataManager = MediaDataManager(context, backgroundExecutor, foregroundExecutor,
mediaControllerFactory, broadcastDispatcher, dumpManager,
- mediaTimeoutListener, mediaResumeListener, useMediaResumption = true,
- useQsMediaPlayer = true)
+ mediaTimeoutListener, mediaResumeListener, activityStarter,
+ useMediaResumption = true, useQsMediaPlayer = true)
session = MediaSession(context, "MediaDataManagerTestSession")
mediaNotification = SbnBuilder().run {
setPkg(PACKAGE_NAME)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt
new file mode 100644
index 000000000000..118cffc2d5b8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2020 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.media
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+public class MediaPlayerDataTest : SysuiTestCase() {
+
+ companion object {
+ val LOCAL = true
+ val RESUMPTION = true
+ }
+
+ @Before
+ fun setup() {
+ MediaPlayerData.clear()
+ }
+
+ @Test
+ fun addPlayingThenRemote() {
+ val playerIsPlaying = mock(MediaControlPanel::class.java)
+ whenever(playerIsPlaying.isPlaying).thenReturn(true)
+ val dataIsPlaying = createMediaData(LOCAL, !RESUMPTION)
+
+ val playerIsRemote = mock(MediaControlPanel::class.java)
+ whenever(playerIsRemote.isPlaying).thenReturn(false)
+ val dataIsRemote = createMediaData(!LOCAL, !RESUMPTION)
+
+ MediaPlayerData.addMediaPlayer("1", dataIsPlaying, playerIsPlaying)
+ MediaPlayerData.addMediaPlayer("2", dataIsRemote, playerIsRemote)
+
+ val players = MediaPlayerData.players()
+ assertThat(players).hasSize(2)
+ assertThat(players).containsExactly(playerIsPlaying, playerIsRemote).inOrder()
+ }
+
+ @Test
+ fun switchPlayersPlaying() {
+ val playerIsPlaying1 = mock(MediaControlPanel::class.java)
+ whenever(playerIsPlaying1.isPlaying).thenReturn(true)
+ val dataIsPlaying1 = createMediaData(LOCAL, !RESUMPTION)
+
+ val playerIsPlaying2 = mock(MediaControlPanel::class.java)
+ whenever(playerIsPlaying2.isPlaying).thenReturn(false)
+ val dataIsPlaying2 = createMediaData(LOCAL, !RESUMPTION)
+
+ MediaPlayerData.addMediaPlayer("1", dataIsPlaying1, playerIsPlaying1)
+ MediaPlayerData.addMediaPlayer("2", dataIsPlaying2, playerIsPlaying2)
+
+ whenever(playerIsPlaying1.isPlaying).thenReturn(false)
+ whenever(playerIsPlaying2.isPlaying).thenReturn(true)
+
+ MediaPlayerData.addMediaPlayer("1", dataIsPlaying1, playerIsPlaying1)
+ MediaPlayerData.addMediaPlayer("2", dataIsPlaying2, playerIsPlaying2)
+
+ val players = MediaPlayerData.players()
+ assertThat(players).hasSize(2)
+ assertThat(players).containsExactly(playerIsPlaying2, playerIsPlaying1).inOrder()
+ }
+
+ @Test
+ fun fullOrderTest() {
+ val playerIsPlaying = mock(MediaControlPanel::class.java)
+ whenever(playerIsPlaying.isPlaying).thenReturn(true)
+ val dataIsPlaying = createMediaData(LOCAL, !RESUMPTION)
+
+ val playerIsPlayingAndRemote = mock(MediaControlPanel::class.java)
+ whenever(playerIsPlayingAndRemote.isPlaying).thenReturn(true)
+ val dataIsPlayingAndRemote = createMediaData(!LOCAL, !RESUMPTION)
+
+ val playerIsStoppedAndLocal = mock(MediaControlPanel::class.java)
+ whenever(playerIsStoppedAndLocal.isPlaying).thenReturn(false)
+ val dataIsStoppedAndLocal = createMediaData(LOCAL, !RESUMPTION)
+
+ val playerIsStoppedAndRemote = mock(MediaControlPanel::class.java)
+ whenever(playerIsStoppedAndLocal.isPlaying).thenReturn(false)
+ val dataIsStoppedAndRemote = createMediaData(!LOCAL, !RESUMPTION)
+
+ val playerCanResume = mock(MediaControlPanel::class.java)
+ whenever(playerCanResume.isPlaying).thenReturn(false)
+ val dataCanResume = createMediaData(LOCAL, RESUMPTION)
+
+ MediaPlayerData.addMediaPlayer("3", dataIsStoppedAndLocal, playerIsStoppedAndLocal)
+ MediaPlayerData.addMediaPlayer("5", dataIsStoppedAndRemote, playerIsStoppedAndRemote)
+ MediaPlayerData.addMediaPlayer("4", dataCanResume, playerCanResume)
+ MediaPlayerData.addMediaPlayer("1", dataIsPlaying, playerIsPlaying)
+ MediaPlayerData.addMediaPlayer("2", dataIsPlayingAndRemote, playerIsPlayingAndRemote)
+
+ val players = MediaPlayerData.players()
+ assertThat(players).hasSize(5)
+ assertThat(players).containsExactly(playerIsPlaying, playerIsPlayingAndRemote,
+ playerIsStoppedAndLocal, playerCanResume, playerIsStoppedAndRemote).inOrder()
+ }
+
+ private fun createMediaData(isLocalSession: Boolean, resumption: Boolean) =
+ MediaData(0, false, 0, null, null, null, null, null, emptyList(), emptyList<Int>(), "",
+ null, null, null, true, null, isLocalSession, resumption, null, false)
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index d338cbf51fb5..9922d3620a57 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -150,7 +150,10 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
return new QSFragment(
new RemoteInputQuickSettingsDisabler(context, mock(ConfigurationController.class),
commandQueue),
- new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()),
+ new InjectionInflationController(
+ SystemUIFactory.getInstance()
+ .getRootComponent()
+ .createViewInstanceCreatorFactory()),
mock(QSTileHost.class),
mock(StatusBarStateController.class),
commandQueue,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index bdb7166f5db1..c8e1a74d969f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -78,7 +78,7 @@ import javax.inject.Provider;
@RunWith(AndroidTestingRunner.class)
@SmallTest
-@RunWithLooper
+@RunWithLooper(setAsMainLooper = true)
public class QSTileHostTest extends SysuiTestCase {
private static String MOCK_STATE_STRING = "MockState";
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
index c2579dd46e78..3aa40dec1fad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
@@ -53,7 +53,7 @@ import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(AndroidTestingRunner::class)
-@TestableLooper.RunWithLooper
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
class CustomTileTest : SysuiTestCase() {
companion object {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
index f70106a64968..2006a75c0e16 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
@@ -38,7 +38,7 @@ import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
-@RunWithLooper
+@RunWithLooper(setAsMainLooper = true)
@SmallTest
class BatterySaverTileTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
index 8ece62281f77..5d14898cdd2c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
@@ -58,7 +58,7 @@ import java.util.List;
@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
public class CastTileTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 14994d55852f..54ccc4d8320d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -79,7 +79,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -117,7 +117,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
@Mock private VisualStabilityManager mVisualStabilityManager;
@Mock private NotificationPresenter mPresenter;
@Mock private NotificationActivityStarter mNotificationActivityStarter;
- @Mock private NotificationStackScrollLayout mStackScroller;
+ @Mock private NotificationListContainer mNotificationListContainer;
@Mock private NotificationInfo.CheckSaveListener mCheckSaveListener;
@Mock private OnSettingsClickListener mOnSettingsClickListener;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@@ -156,7 +156,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
mChannelEditorDialogController, mContextTracker, mProvider,
mAssistantFeedbackController, mBubbleController,
new UiEventLoggerFake());
- mGutsManager.setUpWithPresenter(mPresenter, mStackScroller,
+ mGutsManager.setUpWithPresenter(mPresenter, mNotificationListContainer,
mCheckSaveListener, mOnSettingsClickListener);
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index ddac2ecbd6eb..fec467706b7b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -64,6 +64,7 @@ import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -197,7 +198,10 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
mEntryManager.setUpWithPresenter(mock(NotificationPresenter.class));
when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
+ NotificationShelfController notificationShelfController =
+ mock(NotificationShelfController.class);
NotificationShelf notificationShelf = mock(NotificationShelf.class);
+ when(notificationShelfController.getView()).thenReturn(notificationShelf);
when(mNotificationSectionsManager.createSectionsForBuckets()).thenReturn(
new NotificationSection[]{
mNotificationSection
@@ -208,7 +212,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
// holds a copy of the CUT's instances of these KeyguardBypassController, so they still
// refer to the CUT's member variables, not the spy's member variables.
mStackScrollerInternal = new NotificationStackScrollLayout(getContext(), null,
- true /* allowLongPress */, mNotificationRoundnessManager,
+ mNotificationRoundnessManager,
mock(DynamicPrivacyController.class),
mock(SysuiStatusBarStateController.class),
mHeadsUpManager,
@@ -230,7 +234,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
verify(mLockscreenUserManager).addUserChangedListener(userChangedCaptor.capture());
mUserChangedListener = userChangedCaptor.getValue();
mStackScroller = spy(mStackScrollerInternal);
- mStackScroller.setShelf(notificationShelf);
+ mStackScroller.setShelfController(notificationShelfController);
mStackScroller.setStatusBar(mBar);
mStackScroller.setScrimController(mock(ScrimController.class));
mStackScroller.setGroupManager(mGroupManager);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index e546dff8abf6..8dea84c4d0b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -38,7 +38,7 @@ import com.android.systemui.statusbar.HeadsUpStatusBarView;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Assert;
@@ -51,8 +51,8 @@ import org.junit.runner.RunWith;
@RunWithLooper
public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
- private final NotificationStackScrollLayout mStackScroller =
- mock(NotificationStackScrollLayout.class);
+ private final NotificationStackScrollLayoutController mStackScrollerController =
+ mock(NotificationStackScrollLayoutController.class);
private final NotificationPanelViewController mPanelView =
mock(NotificationPanelViewController.class);
private final DarkIconDispatcher mDarkIconDispatcher = mock(DarkIconDispatcher.class);
@@ -93,9 +93,9 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
mWakeUpCoordinator,
mKeyguardStateController,
mCommandQueue,
- mHeadsUpStatusBarView,
- mStackScroller,
+ mStackScrollerController,
mPanelView,
+ mHeadsUpStatusBarView,
new View(mContext),
mOperatorNameView,
new View(mContext));
@@ -172,9 +172,9 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
mWakeUpCoordinator,
mKeyguardStateController,
mCommandQueue,
- mHeadsUpStatusBarView,
- mStackScroller,
+ mStackScrollerController,
mPanelView,
+ mHeadsUpStatusBarView,
new View(mContext),
new View(mContext),
new View(mContext));
@@ -193,14 +193,14 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
reset(mHeadsUpManager);
reset(mDarkIconDispatcher);
reset(mPanelView);
- reset(mStackScroller);
+ reset(mStackScrollerController);
mHeadsUpAppearanceController.destroy();
verify(mHeadsUpManager).removeListener(any());
verify(mDarkIconDispatcher).removeDarkReceiver((DarkIconDispatcher.DarkReceiver) any());
verify(mPanelView).removeVerticalTranslationListener(any());
verify(mPanelView).removeTrackingHeadsUpListener(any());
verify(mPanelView).setHeadsUpAppearanceController(any());
- verify(mStackScroller).removeOnExpandedHeightChangedListener(any());
- verify(mStackScroller).removeOnLayoutChangeListener(any());
+ verify(mStackScrollerController).removeOnExpandedHeightChangedListener(any());
+ verify(mStackScrollerController).removeOnLayoutChangeListener(any());
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index c7434f6fd95f..a0c0e7979084 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -63,7 +63,7 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationShelf;
+import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -74,6 +74,7 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.ZenModeController;
@@ -115,7 +116,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
@Mock
private HeadsUpManagerPhone mHeadsUpManager;
@Mock
- private NotificationShelf mNotificationShelf;
+ private NotificationShelfController mNotificationShelfController;
@Mock
private NotificationGroupManager mGroupManager;
@Mock
@@ -186,7 +187,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Mock
private KeyguardClockSwitchController mKeyguardClockSwitchController;
- private FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder;
+ @Mock
+ private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
private NotificationPanelViewController mNotificationPanelViewController;
private View.AccessibilityDelegate mAccessibiltyDelegate;
@@ -205,14 +207,18 @@ public class NotificationPanelViewTest extends SysuiTestCase {
when(mView.findViewById(R.id.keyguard_clock_container)).thenReturn(mKeyguardClockSwitch);
when(mView.findViewById(R.id.notification_stack_scroller))
.thenReturn(mNotificationStackScrollLayout);
- when(mNotificationStackScrollLayout.getHeight()).thenReturn(1000);
- when(mNotificationStackScrollLayout.getHeadsUpCallback()).thenReturn(mHeadsUpCallback);
+ when(mNotificationStackScrollLayout.getController())
+ .thenReturn(mNotificationStackScrollLayoutController);
+ when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(1000);
+ when(mNotificationStackScrollLayoutController.getHeadsUpCallback())
+ .thenReturn(mHeadsUpCallback);
when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea);
when(mKeyguardBottomArea.getLeftView()).thenReturn(mock(KeyguardAffordanceView.class));
when(mKeyguardBottomArea.getRightView()).thenReturn(mock(KeyguardAffordanceView.class));
when(mView.findViewById(R.id.big_clock_container)).thenReturn(mBigClockContainer);
when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
- mFlingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(mDisplayMetrics);
+ FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(
+ mDisplayMetrics);
doAnswer((Answer<Void>) invocation -> {
mTouchHandler = invocation.getArgument(0);
@@ -241,19 +247,19 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mDozeParameters, mCommandQueue, mVibratorHelper,
mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor,
mMetricsLogger, mActivityManager, mZenModeController, mConfigurationController,
- mFlingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
+ flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
mConversationNotificationManager, mMediaHiearchyManager,
mBiometricUnlockController, mStatusBarKeyguardViewManager,
- () -> mKeyguardClockSwitchController);
+ () -> mKeyguardClockSwitchController,
+ mNotificationStackScrollLayoutController);
mNotificationPanelViewController.initDependencies(mStatusBar, mGroupManager,
- mNotificationShelf, mNotificationAreaController, mScrimController);
+ mNotificationShelfController, mNotificationAreaController, mScrimController);
mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
mNotificationPanelViewController.setBar(mPanelBar);
ArgumentCaptor<View.AccessibilityDelegate> accessibilityDelegateArgumentCaptor =
ArgumentCaptor.forClass(View.AccessibilityDelegate.class);
- verify(mView)
- .setAccessibilityDelegate(accessibilityDelegateArgumentCaptor.capture());
+ verify(mView).setAccessibilityDelegate(accessibilityDelegateArgumentCaptor.capture());
mAccessibiltyDelegate = accessibilityDelegateArgumentCaptor.getValue();
}
@@ -261,8 +267,10 @@ public class NotificationPanelViewTest extends SysuiTestCase {
public void testSetDozing_notifiesNsslAndStateController() {
mNotificationPanelViewController.setDozing(true /* dozing */, true /* animate */,
null /* touch */);
- InOrder inOrder = inOrder(mNotificationStackScrollLayout, mStatusBarStateController);
- inOrder.verify(mNotificationStackScrollLayout).setDozing(eq(true), eq(true), eq(null));
+ InOrder inOrder = inOrder(
+ mNotificationStackScrollLayoutController, mStatusBarStateController);
+ inOrder.verify(mNotificationStackScrollLayoutController)
+ .setDozing(eq(true), eq(true), eq(null));
inOrder.verify(mStatusBarStateController).setDozeAmount(eq(1f), eq(true));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java
index e04d25b17c71..51900cb7dda1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java
@@ -100,7 +100,9 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
mController = new NotificationShadeWindowViewController(
new InjectionInflationController(
- SystemUIFactory.getInstance().getRootComponent()),
+ SystemUIFactory.getInstance()
+ .getRootComponent()
+ .createViewInstanceCreatorFactory()),
mCoordinator,
mPulseExpansionHandler,
mDynamicPrivacyController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index 318e9b87fa70..e4f481241257 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -23,13 +23,11 @@ import static org.mockito.Mockito.when;
import android.app.Notification;
import android.app.StatusBarManager;
-import android.content.Context;
import android.metrics.LogMaker;
import android.support.test.metricshelper.MetricsAsserts;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
-import android.view.ViewGroup;
import androidx.test.filters.SmallTest;
@@ -59,6 +57,8 @@ import com.android.systemui.statusbar.notification.interruption.NotificationInte
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Before;
@@ -112,11 +112,17 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase {
NotificationShadeWindowView notificationShadeWindowView =
mock(NotificationShadeWindowView.class);
+ NotificationStackScrollLayoutController stackScrollLayoutController =
+ mock(NotificationStackScrollLayoutController.class);
+ when(stackScrollLayoutController.getView()).thenReturn(
+ mock(NotificationStackScrollLayout.class));
+ when(stackScrollLayoutController.getNotificationListContainer()).thenReturn(
+ mock(NotificationListContainer.class));
when(notificationShadeWindowView.getResources()).thenReturn(mContext.getResources());
mStatusBarNotificationPresenter = new StatusBarNotificationPresenter(mContext,
mock(NotificationPanelViewController.class), mock(HeadsUpManagerPhone.class),
- notificationShadeWindowView, mock(NotificationListContainerViewGroup.class),
+ notificationShadeWindowView, stackScrollLayoutController,
mock(DozeScrimController.class), mock(ScrimController.class),
mock(ActivityLaunchAnimator.class), mock(DynamicPrivacyController.class),
mock(KeyguardStateController.class),
@@ -205,14 +211,4 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase {
new LogMaker(MetricsEvent.ACTION_LS_NOTE)
.setType(MetricsEvent.TYPE_ACTION));
}
-
- // We need this because mockito doesn't know how to construct a mock that extends ViewGroup
- // and implements NotificationListContainer without it because of classloader issues.
- private abstract static class NotificationListContainerViewGroup extends ViewGroup
- implements NotificationListContainer {
-
- public NotificationListContainerViewGroup(Context context) {
- super(context);
- }
- }
}
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 5a08c9ca017b..a385d81331ed 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
@@ -124,7 +124,9 @@ import com.android.systemui.statusbar.notification.interruption.NotificationInte
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.logging.NotificationPanelLoggerFake;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -171,6 +173,8 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private KeyguardStateController mKeyguardStateController;
@Mock private KeyguardIndicationController mKeyguardIndicationController;
@Mock private NotificationStackScrollLayout mStackScroller;
+ @Mock private NotificationStackScrollLayoutController mStackScrollerController;
+ @Mock private NotificationListContainer mNotificationListContainer;
@Mock private HeadsUpManagerPhone mHeadsUpManager;
@Mock private NotificationPanelViewController mNotificationPanelViewController;
@Mock private NotificationPanelView mNotificationPanelView;
@@ -283,6 +287,10 @@ public class StatusBarTest extends SysuiTestCase {
mContext.setTheme(R.style.Theme_SystemUI_Light);
+ when(mStackScroller.getController()).thenReturn(mStackScrollerController);
+ when(mStackScrollerController.getView()).thenReturn(mStackScroller);
+ when(mStackScrollerController.getNotificationListContainer()).thenReturn(
+ mNotificationListContainer);
when(mStackScroller.generateLayoutParams(any())).thenReturn(new LayoutParams(0, 0));
when(mNotificationPanelViewController.getView()).thenReturn(mNotificationPanelView);
when(mNotificationPanelView.getLayoutParams()).thenReturn(new LayoutParams(0, 0));
@@ -429,7 +437,7 @@ public class StatusBarTest extends SysuiTestCase {
mStatusBar.mStackScroller = mStackScroller;
mStatusBar.startKeyguard();
mInitController.executePostInitTasks();
- notificationLogger.setUpWithContainer(mStackScroller);
+ notificationLogger.setUpWithContainer(mNotificationListContainer);
}
@Test
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt
index 4b6bbac051e0..75c819bb0ced 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringNotificationUpdaterTest.kt
@@ -18,33 +18,40 @@ package com.android.networkstack.tethering
import android.app.Notification
import android.app.NotificationManager
+import android.app.PendingIntent
+import android.app.PendingIntent.FLAG_IMMUTABLE
import android.content.Context
+import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.content.res.Resources
import android.net.ConnectivityManager.TETHERING_WIFI
+import android.net.NetworkCapabilities
+import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
-import android.net.NetworkCapabilities
-import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING
import android.os.UserHandle
+import android.provider.Settings
import android.telephony.TelephonyManager
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.AndroidJUnit4
import com.android.internal.util.test.BroadcastInterceptingContext
+import com.android.networkstack.tethering.TetheringNotificationUpdater.ACTION_DISABLE_TETHERING
import com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE
import com.android.networkstack.tethering.TetheringNotificationUpdater.EVENT_SHOW_NO_UPSTREAM
import com.android.networkstack.tethering.TetheringNotificationUpdater.NO_UPSTREAM_NOTIFICATION_ID
import com.android.networkstack.tethering.TetheringNotificationUpdater.RESTRICTED_NOTIFICATION_ID
import com.android.networkstack.tethering.TetheringNotificationUpdater.ROAMING_NOTIFICATION_ID
import com.android.networkstack.tethering.TetheringNotificationUpdater.VERIZON_CARRIER_ID
+import com.android.networkstack.tethering.TetheringNotificationUpdater.getSettingsPackageName
import com.android.testutils.waitForIdle
import org.junit.After
import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
import org.junit.Assert.fail
import org.junit.Before
import org.junit.Test
@@ -87,12 +94,17 @@ class TetheringNotificationUpdaterTest {
// every test but should always be initialized before use (or the test should crash).
private lateinit var context: TestContext
private lateinit var notificationUpdater: TetheringNotificationUpdater
+
+ // Initializing the following members depends on initializing some of the mocks and
+ // is more logically done in setup().
private lateinit var fakeTetheringThread: HandlerThread
private val ROAMING_CAPABILITIES = NetworkCapabilities()
private val HOME_CAPABILITIES = NetworkCapabilities().addCapability(NET_CAPABILITY_NOT_ROAMING)
private val NOTIFICATION_ICON_ID = R.drawable.stat_sys_tether_general
private val TIMEOUT_MS = 500L
+ private val ACTIVITY_PENDING_INTENT = 0
+ private val BROADCAST_PENDING_INTENT = 1
private inner class TestContext(c: Context) : BroadcastInterceptingContext(c) {
override fun createContextAsUser(user: UserHandle, flags: Int) =
@@ -146,10 +158,43 @@ class TetheringNotificationUpdaterTest {
fakeTetheringThread.quitSafely()
}
+ private fun verifyActivityPendingIntent(intent: Intent, flags: Int) {
+ // Use FLAG_NO_CREATE to verify whether PendingIntent has FLAG_IMMUTABLE flag(forcefully add
+ // the flag in creating arguments). If the described PendingIntent does not already exist,
+ // getActivity() will return null instead of PendingIntent object.
+ val pi = PendingIntent.getActivity(
+ context.createContextAsUser(UserHandle.CURRENT, 0 /* flags */),
+ 0 /* requestCode */,
+ intent,
+ flags or FLAG_IMMUTABLE or PendingIntent.FLAG_NO_CREATE,
+ null /* options */)
+ assertNotNull("Activity PendingIntent with FLAG_IMMUTABLE does not exist.", pi)
+ }
+
+ private fun verifyBroadcastPendingIntent(intent: Intent, flags: Int) {
+ // Use FLAG_NO_CREATE to verify whether PendingIntent has FLAG_IMMUTABLE flag(forcefully add
+ // the flag in creating arguments). If the described PendingIntent does not already exist,
+ // getBroadcast() will return null instead of PendingIntent object.
+ val pi = PendingIntent.getBroadcast(
+ context.createContextAsUser(UserHandle.CURRENT, 0 /* flags */),
+ 0 /* requestCode */,
+ intent,
+ flags or FLAG_IMMUTABLE or PendingIntent.FLAG_NO_CREATE)
+ assertNotNull("Broadcast PendingIntent with FLAG_IMMUTABLE does not exist.", pi)
+ }
+
private fun Notification.title() = this.extras.getString(Notification.EXTRA_TITLE)
private fun Notification.text() = this.extras.getString(Notification.EXTRA_TEXT)
- private fun verifyNotification(iconId: Int, title: String, text: String, id: Int) {
+ private fun verifyNotification(
+ iconId: Int,
+ title: String,
+ text: String,
+ id: Int,
+ intentSenderType: Int,
+ intent: Intent,
+ flags: Int
+ ) {
verify(notificationManager, never()).cancel(any(), eq(id))
val notificationCaptor = ArgumentCaptor.forClass(Notification::class.java)
@@ -161,6 +206,11 @@ class TetheringNotificationUpdaterTest {
assertEquals(title, notification.title())
assertEquals(text, notification.text())
+ when (intentSenderType) {
+ ACTIVITY_PENDING_INTENT -> verifyActivityPendingIntent(intent, flags)
+ BROADCAST_PENDING_INTENT -> verifyBroadcastPendingIntent(intent, flags)
+ }
+
reset(notificationManager)
}
@@ -176,6 +226,10 @@ class TetheringNotificationUpdaterTest {
@Test
fun testRestrictedNotification() {
+ val settingsIntent = Intent(Settings.ACTION_TETHER_SETTINGS)
+ .setPackage(getSettingsPackageName(context.packageManager))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+
// Set test sub id.
notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
@@ -183,7 +237,7 @@ class TetheringNotificationUpdaterTest {
// User restrictions on. Show restricted notification.
notificationUpdater.notifyTetheringDisabledByRestriction()
verifyNotification(NOTIFICATION_ICON_ID, TEST_DISALLOW_TITLE, TEST_DISALLOW_MESSAGE,
- RESTRICTED_NOTIFICATION_ID)
+ RESTRICTED_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE)
// User restrictions off. Clear notification.
notificationUpdater.tetheringRestrictionLifted()
@@ -196,7 +250,7 @@ class TetheringNotificationUpdaterTest {
// User restrictions on again. Show restricted notification.
notificationUpdater.notifyTetheringDisabledByRestriction()
verifyNotification(NOTIFICATION_ICON_ID, TEST_DISALLOW_TITLE, TEST_DISALLOW_MESSAGE,
- RESTRICTED_NOTIFICATION_ID)
+ RESTRICTED_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE)
}
val MAX_BACKOFF_MS = 200L
@@ -234,6 +288,8 @@ class TetheringNotificationUpdaterTest {
@Test
fun testNoUpstreamNotification() {
+ val disableIntent = Intent(ACTION_DISABLE_TETHERING).setPackage(context.packageName)
+
// Set test sub id.
notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
@@ -246,7 +302,8 @@ class TetheringNotificationUpdaterTest {
notificationUpdater.onUpstreamCapabilitiesChanged(null)
notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS)
verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
- NO_UPSTREAM_NOTIFICATION_ID)
+ NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent,
+ FLAG_IMMUTABLE)
// Same capabilities changed. Nothing happened.
notificationUpdater.onUpstreamCapabilitiesChanged(null)
@@ -260,7 +317,8 @@ class TetheringNotificationUpdaterTest {
notificationUpdater.onUpstreamCapabilitiesChanged(null)
notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS)
verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
- NO_UPSTREAM_NOTIFICATION_ID)
+ NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent,
+ FLAG_IMMUTABLE)
// No downstream.
notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
@@ -305,6 +363,11 @@ class TetheringNotificationUpdaterTest {
@Test
fun testRoamingNotification() {
+ val disableIntent = Intent(ACTION_DISABLE_TETHERING).setPackage(context.packageName)
+ val settingsIntent = Intent(Settings.ACTION_TETHER_SETTINGS)
+ .setPackage(getSettingsPackageName(context.packageManager))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+
// Set test sub id.
notificationUpdater.onActiveDataSubscriptionIdChanged(TEST_SUBID)
verifyNotificationCancelled(listOf(NO_UPSTREAM_NOTIFICATION_ID, ROAMING_NOTIFICATION_ID))
@@ -316,7 +379,7 @@ class TetheringNotificationUpdaterTest {
// Upstream capabilities changed to roaming state. Show roaming notification.
notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES)
verifyNotification(NOTIFICATION_ICON_ID, TEST_ROAMING_TITLE, TEST_ROAMING_MESSAGE,
- ROAMING_NOTIFICATION_ID)
+ ROAMING_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE)
// Same capabilities change. Nothing happened.
notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES)
@@ -329,14 +392,15 @@ class TetheringNotificationUpdaterTest {
// Upstream capabilities changed to roaming state again. Show roaming notification.
notificationUpdater.onUpstreamCapabilitiesChanged(ROAMING_CAPABILITIES)
verifyNotification(NOTIFICATION_ICON_ID, TEST_ROAMING_TITLE, TEST_ROAMING_MESSAGE,
- ROAMING_NOTIFICATION_ID)
+ ROAMING_NOTIFICATION_ID, ACTIVITY_PENDING_INTENT, settingsIntent, FLAG_IMMUTABLE)
// No upstream. Clear roaming notification and show no upstream notification.
notificationUpdater.onUpstreamCapabilitiesChanged(null)
notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS)
verifyNotificationCancelled(listOf(ROAMING_NOTIFICATION_ID), false)
verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
- NO_UPSTREAM_NOTIFICATION_ID)
+ NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent,
+ FLAG_IMMUTABLE)
// No downstream.
notificationUpdater.onDownstreamChanged(DOWNSTREAM_NONE)
@@ -347,7 +411,8 @@ class TetheringNotificationUpdaterTest {
notificationUpdater.handler.waitForDelayedMessage(EVENT_SHOW_NO_UPSTREAM, TIMEOUT_MS)
verifyNotificationCancelled(listOf(ROAMING_NOTIFICATION_ID), false)
verifyNotification(NOTIFICATION_ICON_ID, TEST_NO_UPSTREAM_TITLE, TEST_NO_UPSTREAM_MESSAGE,
- NO_UPSTREAM_NOTIFICATION_ID)
+ NO_UPSTREAM_NOTIFICATION_ID, BROADCAST_PENDING_INTENT, disableIntent,
+ FLAG_IMMUTABLE)
// Set R.bool.config_upstream_roaming_notification to false and change upstream
// network to roaming state again. No roaming notification.
@@ -363,8 +428,7 @@ class TetheringNotificationUpdaterTest {
val testSettingsPackageName = "com.android.test.settings"
val pm = mock(PackageManager::class.java)
doReturn(null).`when`(pm).resolveActivity(any(), anyInt())
- assertEquals(defaultSettingsPackageName,
- TetheringNotificationUpdater.getSettingsPackageName(pm))
+ assertEquals(defaultSettingsPackageName, getSettingsPackageName(pm))
val resolveInfo = ResolveInfo().apply {
activityInfo = ActivityInfo().apply {
@@ -375,7 +439,6 @@ class TetheringNotificationUpdaterTest {
}
}
doReturn(resolveInfo).`when`(pm).resolveActivity(any(), anyInt())
- assertEquals(testSettingsPackageName,
- TetheringNotificationUpdater.getSettingsPackageName(pm))
+ assertEquals(testSettingsPackageName, getSettingsPackageName(pm))
}
}
diff --git a/services/Android.bp b/services/Android.bp
index ef52c2aff002..b348b91a1bd7 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -156,14 +156,10 @@ droidstubs {
java_library {
name: "android_system_server_stubs_current",
- defaults: ["android_stubs_dists_default"],
srcs: [":services-stubs.sources"],
installable: false,
static_libs: ["android_module_lib_stubs_current"],
sdk_version: "none",
system_modules: "none",
java_version: "1.8",
- dist: {
- dir: "apistubs/android/system-server",
- },
}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index e1baefed4425..a2d58c8019fc 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -609,6 +609,9 @@ public class TouchExplorer extends BaseEventStreamTransformation
mSendHoverExitDelayed.cancel();
if (mGestureDetector.isMultiFingerGesturesEnabled()
&& mGestureDetector.isTwoFingerPassthroughEnabled()) {
+ if (pointerIndex < 0) {
+ return;
+ }
final float deltaX =
mReceivedPointerTracker.getReceivedPointerDownX(pointerId)
- rawEvent.getX(pointerIndex);
@@ -628,7 +631,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
// Two pointers moving in the same direction within
// a given distance perform a drag.
mState.startDragging();
- adjustEventLocationForDrag(event);
+ computeDraggingPointerIdIfNeeded(event);
pointerIdBits = 1 << mDraggingPointerId;
event.setEdgeFlags(mReceivedPointerTracker.getLastReceivedDownEdgeFlags());
mDispatcher.sendMotionEvent(
@@ -791,7 +794,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
case 2:
if (isDraggingGesture(event)) {
// If still dragging send a drag event.
- adjustEventLocationForDrag(event);
+ computeDraggingPointerIdIfNeeded(event);
mDispatcher.sendMotionEvent(
event, ACTION_MOVE, rawEvent, pointerIdBits, policyFlags);
} else {
@@ -956,37 +959,27 @@ public class TouchExplorer extends BaseEventStreamTransformation
}
/**
- * Adjust the location of an injected event when performing a drag. The location will be the
- * location of the finger closest to an edge of the screen.
+ * Computes {@link #mDraggingPointerId} if it is invalid. The pointer will be the finger
+ * closet to an edge of the screen.
*/
- private void adjustEventLocationForDrag(MotionEvent event) {
+ private void computeDraggingPointerIdIfNeeded(MotionEvent event) {
+ if (mDraggingPointerId != INVALID_POINTER_ID) {
+ // If we have a valid pointer ID, we should be good
+ final int pointerIndex = event.findPointerIndex(mDraggingPointerId);
+ if (event.findPointerIndex(pointerIndex) >= 0) {
+ return;
+ }
+ }
+ // Use the pointer that is closest to its closest edge.
final float firstPtrX = event.getX(0);
final float firstPtrY = event.getY(0);
final int firstPtrId = event.getPointerId(0);
final float secondPtrX = event.getX(1);
final float secondPtrY = event.getY(1);
final int secondPtrId = event.getPointerId(1);
- float draggingX;
- float draggingY;
- if (mDraggingPointerId == INVALID_POINTER_ID) {
- // The goal is to use the coordinates of the finger that is closest to its closest edge.
- if (getDistanceToClosestEdge(firstPtrX, firstPtrY)
- < getDistanceToClosestEdge(secondPtrX, secondPtrY)) {
- draggingX = firstPtrX;
- draggingY = firstPtrY;
- mDraggingPointerId = firstPtrId;
- } else {
- draggingX = secondPtrX;
- draggingY = secondPtrY;
- mDraggingPointerId = secondPtrId;
- }
- } else {
- // Just use the coordinates of the dragging pointer.
- int pointerIndex = event.findPointerIndex(mDraggingPointerId);
- draggingX = event.getX(pointerIndex);
- draggingY = event.getY(pointerIndex);
- }
- event.setLocation(draggingX, draggingY);
+ mDraggingPointerId = (getDistanceToClosestEdge(firstPtrX, firstPtrY)
+ < getDistanceToClosestEdge(secondPtrX, secondPtrY))
+ ? firstPtrId : secondPtrId;
}
private float getDistanceToClosestEdge(float x, float y) {
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
index bd25f2bea881..3ee5b28ee338 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
@@ -25,10 +25,12 @@ import static java.util.Arrays.copyOfRange;
import android.annotation.Nullable;
import android.content.Context;
+import android.graphics.Point;
import android.provider.Settings;
import android.util.Log;
import android.util.MathUtils;
import android.util.Slog;
+import android.view.Display;
import android.view.MotionEvent;
import com.android.internal.annotations.VisibleForTesting;
@@ -90,6 +92,8 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl
private MotionEventDispatcherDelegate mMotionEventDispatcherDelegate;
private final int mDisplayId;
+ private final Context mContext;
+ private final Point mTempPoint = new Point();
private final Queue<MotionEvent> mDebugOutputEventHistory;
@@ -107,7 +111,7 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl
Slog.i(LOG_TAG,
"WindowMagnificationGestureHandler() , displayId = " + displayId + ")");
}
-
+ mContext = context;
mWindowMagnificationMgr = windowMagnificationMgr;
mDetectShortcutTrigger = detectShortcutTrigger;
mDisplayId = displayId;
@@ -184,7 +188,14 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl
if (!mDetectShortcutTrigger) {
return;
}
- toggleMagnification(Float.NaN, Float.NaN);
+ final Point screenSize = mTempPoint;
+ getScreenSize(mTempPoint);
+ toggleMagnification(screenSize.x / 2.0f, screenSize.y / 2.0f);
+ }
+
+ private void getScreenSize(Point outSize) {
+ final Display display = mContext.getDisplay();
+ display.getRealSize(outSize);
}
@Override
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 1c3116699b2d..a92d334a94fa 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -27,6 +27,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
@@ -214,7 +215,13 @@ final class SaveUi {
return componentName;
}
intent.addFlags(Intent.FLAG_ACTIVITY_MATCH_EXTERNAL);
- return intent.resolveActivity(packageManager);
+ final ActivityInfo ai =
+ intent.resolveActivityInfo(packageManager, PackageManager.MATCH_INSTANT);
+ if (ai != null) {
+ return new ComponentName(ai.applicationInfo.packageName, ai.name);
+ }
+
+ return null;
}
};
final LayoutInflater inflater = LayoutInflater.from(context);
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 29235dd1ee72..e68c07ed73f7 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -441,6 +441,7 @@ public class UserBackupManagerService {
private long mAncestralToken = 0;
private long mCurrentToken = 0;
@Nullable private File mAncestralSerialNumberFile;
+ @OperationType private volatile long mAncestralOperationType;
private final ContentObserver mSetupObserver;
private final BroadcastReceiver mRunInitReceiver;
@@ -881,6 +882,10 @@ public class UserBackupManagerService {
mAncestralToken = ancestralToken;
}
+ public void setAncestralOperationType(@OperationType int operationType) {
+ mAncestralOperationType = operationType;
+ }
+
public long getCurrentToken() {
return mCurrentToken;
}
@@ -1808,6 +1813,16 @@ public class UserBackupManagerService {
}
}
+ private BackupEligibilityRules getEligibilityRulesForRestoreAtInstall(long restoreToken) {
+ if (mAncestralOperationType == OperationType.MIGRATION && restoreToken == mAncestralToken) {
+ return getEligibilityRulesForOperation(OperationType.MIGRATION);
+ } else {
+ // If we're not using the ancestral data set, it means we're restoring from a backup
+ // that happened on this device.
+ return mScheduledBackupEligibility;
+ }
+ }
+
/**
* Get the restore-set token for the best-available restore set for this {@code packageName}:
* the active set if possible, else the ancestral one. Returns zero if none available.
@@ -3976,7 +3991,7 @@ public class UserBackupManagerService {
packageName,
token,
listener,
- mScheduledBackupEligibility);
+ getEligibilityRulesForRestoreAtInstall(restoreSet));
mBackupHandler.sendMessage(msg);
} catch (Exception e) {
// Calling into the transport broke; back off and proceed with the installation.
diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
index 622067999f27..b9625397d237 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -27,6 +27,7 @@ import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERA
import android.app.ApplicationThreadConstants;
import android.app.IBackupAgent;
+import android.app.backup.BackupManager;
import android.app.backup.FullBackup;
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.IFullBackupRestoreObserver;
@@ -633,7 +634,11 @@ public class FullRestoreEngine extends RestoreEngine {
setRunning(false);
}
- private static boolean isRestorableFile(FileMetadata info) {
+ private boolean isRestorableFile(FileMetadata info) {
+ if (mBackupEligibilityRules.getOperationType() == BackupManager.OperationType.MIGRATION) {
+ // Everything is eligible for device-to-device migration.
+ return true;
+ }
if (FullBackup.CACHE_TREE_TOKEN.equals(info.domain)) {
if (MORE_DEBUG) {
Slog.i(TAG, "Dropping cache file path " + info.path);
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 7baf55992770..abf11bd542a1 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -1136,6 +1136,8 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
if (mIsSystemRestore && mPmAgent != null) {
backupManagerService.setAncestralPackages(mPmAgent.getRestoredPackages());
backupManagerService.setAncestralToken(mToken);
+ backupManagerService.setAncestralOperationType(
+ mBackupEligibilityRules.getOperationType());
backupManagerService.writeRestoreTokens();
}
diff --git a/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java b/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
index d6598975a647..73ba1f19c092 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
@@ -85,12 +85,15 @@ public class BackupEligibilityRules {
* <li>they run as a system-level uid but do not supply their own backup agent
* <li>it is the special shared-storage backup package used for 'adb backup'
* </ol>
+ *
+ * However, the above eligibility rules are ignored for non-system apps in in case of
+ * device-to-device migration, see {@link OperationType}.
*/
@VisibleForTesting
public boolean appIsEligibleForBackup(ApplicationInfo app) {
- // 1. their manifest states android:allowBackup="false"
- boolean appAllowsBackup = (app.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0;
- if (!appAllowsBackup && !forceFullBackup(app.uid, mOperationType)) {
+ // 1. their manifest states android:allowBackup="false" and this is not a device-to-device
+ // migration
+ if (!isAppBackupAllowed(app)) {
return false;
}
@@ -123,6 +126,23 @@ public class BackupEligibilityRules {
}
/**
+ * Check if this app allows backup. Apps can opt out of backup by stating
+ * android:allowBackup="false" in their manifest. However, this flag is ignored for non-system
+ * apps during device-to-device migrations, see {@link OperationType}.
+ *
+ * @param app The app under check.
+ * @return boolean indicating whether backup is allowed.
+ */
+ public boolean isAppBackupAllowed(ApplicationInfo app) {
+ if (mOperationType == OperationType.MIGRATION && !UserHandle.isCore(app.uid)) {
+ // Backup / restore of all apps is force allowed during device-to-device migration.
+ return true;
+ }
+
+ return (app.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0;
+ }
+
+ /**
* Returns whether an app is eligible for backup at runtime. That is, the app has to:
* <ol>
* <li>Return true for {@link #appIsEligibleForBackup(ApplicationInfo, int)}
diff --git a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
index bf8e9c8512ae..3789fa14e87b 100644
--- a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
+++ b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
@@ -402,7 +402,7 @@ public class TarBackupReader {
info.packageName, PackageManager.GET_SIGNING_CERTIFICATES, userId);
// Fall through to IGNORE if the app explicitly disallows backup
final int flags = pkgInfo.applicationInfo.flags;
- if ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0) {
+ if (eligibilityRules.isAppBackupAllowed(pkgInfo.applicationInfo)) {
// Restore system-uid-space packages only if they have
// defined a custom backup agent
if (!UserHandle.isCore(pkgInfo.applicationInfo.uid)
diff --git a/services/core/Android.bp b/services/core/Android.bp
index e76ec743661c..addaa6568665 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -2,38 +2,25 @@ filegroup {
name: "services.core-sources",
srcs: ["java/**/*.java"],
path: "java",
- visibility: ["//frameworks/base/services"],
-}
-
-java_library {
- name: "protolog-common",
- srcs: [
- "java/com/android/server/protolog/common/**/*.java",
- ],
- host_supported: true,
-}
-
-java_library {
- name: "services.core.wm.protologgroups",
- srcs: [
- "java/com/android/server/wm/ProtoLogGroup.java",
+ visibility: [
+ "//frameworks/base/services",
+ "//frameworks/base/core/java/com/android/internal/protolog",
],
- static_libs: ["protolog-common"],
}
genrule {
name: "services.core.protologsrc",
srcs: [
- ":services.core.wm.protologgroups",
+ ":protolog-groups",
":services.core-sources",
],
tools: ["protologtool"],
cmd: "$(location protologtool) transform-protolog-calls " +
- "--protolog-class com.android.server.protolog.common.ProtoLog " +
- "--protolog-impl-class com.android.server.protolog.ProtoLogImpl " +
- "--protolog-cache-class 'com.android.server.protolog.ProtoLog$$Cache' " +
- "--loggroups-class com.android.server.wm.ProtoLogGroup " +
- "--loggroups-jar $(location :services.core.wm.protologgroups) " +
+ "--protolog-class com.android.internal.protolog.common.ProtoLog " +
+ "--protolog-impl-class com.android.internal.protolog.ProtoLogImpl " +
+ "--protolog-cache-class 'com.android.server.wm.ProtoLogCache' " +
+ "--loggroups-class com.android.internal.protolog.ProtoLogGroup " +
+ "--loggroups-jar $(location :protolog-groups) " +
"--output-srcjar $(out) " +
"$(locations :services.core-sources)",
out: ["services.core.protolog.srcjar"],
@@ -42,14 +29,14 @@ genrule {
genrule {
name: "generate-protolog.json",
srcs: [
- ":services.core.wm.protologgroups",
+ ":protolog-groups",
":services.core-sources",
],
tools: ["protologtool"],
cmd: "$(location protologtool) generate-viewer-config " +
- "--protolog-class com.android.server.protolog.common.ProtoLog " +
- "--loggroups-class com.android.server.wm.ProtoLogGroup " +
- "--loggroups-jar $(location :services.core.wm.protologgroups) " +
+ "--protolog-class com.android.internal.protolog.common.ProtoLog " +
+ "--loggroups-class com.android.internal.protolog.ProtoLogGroup " +
+ "--loggroups-jar $(location :protolog-groups) " +
"--viewer-conf $(out) " +
"$(locations :services.core-sources)",
out: ["services.core.protolog.json"],
@@ -109,6 +96,7 @@ java_library_static {
],
static_libs: [
+ "protolog-lib",
"time_zone_distro",
"time_zone_distro_installer",
"android.hardware.authsecret-V1.0-java",
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index a3c04be02c6f..c9513592ea79 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -28,7 +28,9 @@ import android.database.ContentObserver;
import android.net.Uri;
import android.os.BatteryStatsInternal;
import android.os.Binder;
+import android.os.ParcelFileDescriptor;
import android.os.Process;
+import android.os.ShellCommand;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
@@ -308,50 +310,134 @@ public class BinderCallsStatsService extends Binder {
}
boolean verbose = false;
+ int worksourceUid = Process.INVALID_UID;
if (args != null) {
- for (final String arg : args) {
+ for (int i = 0; i < args.length; i++) {
+ String arg = args[i];
if ("-a".equals(arg)) {
verbose = true;
- } else if ("--reset".equals(arg)) {
+ } else if ("-h".equals(arg)) {
+ pw.println("dumpsys binder_calls_stats options:");
+ pw.println(" -a: Verbose");
+ pw.println(" --work-source-uid <UID>: Dump binder calls from the UID");
+ return;
+ } else if ("--work-source-uid".equals(arg)) {
+ i++;
+ if (i >= args.length) {
+ throw new IllegalArgumentException(
+ "Argument expected after \"" + arg + "\"");
+ }
+ String uidArg = args[i];
+ try {
+ worksourceUid = Integer.parseInt(uidArg);
+ } catch (NumberFormatException e) {
+ pw.println("Invalid UID: " + uidArg);
+ return;
+ }
+ }
+ }
+
+ if (args.length > 0 && worksourceUid == Process.INVALID_UID) {
+ // For compatibility, support "cmd"-style commands when passed to "dumpsys".
+ BinderCallsStatsShellCommand command = new BinderCallsStatsShellCommand(pw);
+ int status = command.exec(this, null, FileDescriptor.out, FileDescriptor.err, args);
+ if (status == 0) {
+ return;
+ }
+ }
+ }
+ mBinderCallsStats.dump(pw, AppIdToPackageMap.getSnapshot(), worksourceUid, verbose);
+ }
+
+ @Override
+ public int handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out,
+ ParcelFileDescriptor err, String[] args) {
+ ShellCommand command = new BinderCallsStatsShellCommand(null);
+ int status = command.exec(this, in.getFileDescriptor(), out.getFileDescriptor(),
+ err.getFileDescriptor(), args);
+ if (status != 0) {
+ command.onHelp();
+ }
+ return status;
+ }
+
+ private class BinderCallsStatsShellCommand extends ShellCommand {
+ private final PrintWriter mPrintWriter;
+
+ BinderCallsStatsShellCommand(PrintWriter printWriter) {
+ mPrintWriter = printWriter;
+ }
+
+ @Override
+ public PrintWriter getOutPrintWriter() {
+ if (mPrintWriter != null) {
+ return mPrintWriter;
+ }
+ return super.getOutPrintWriter();
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ PrintWriter pw = getOutPrintWriter();
+ if (cmd == null) {
+ return -1;
+ }
+
+ switch (cmd) {
+ case "--reset":
reset();
pw.println("binder_calls_stats reset.");
- return;
- } else if ("--enable".equals(arg)) {
+ break;
+ case "--enable":
Binder.setObserver(mBinderCallsStats);
- return;
- } else if ("--disable".equals(arg)) {
+ break;
+ case "--disable":
Binder.setObserver(null);
- return;
- } else if ("--no-sampling".equals(arg)) {
+ break;
+ case "--no-sampling":
mBinderCallsStats.setSamplingInterval(1);
- return;
- } else if ("--enable-detailed-tracking".equals(arg)) {
+ break;
+ case "--enable-detailed-tracking":
SystemProperties.set(PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, "1");
mBinderCallsStats.setDetailedTracking(true);
pw.println("Detailed tracking enabled");
- return;
- } else if ("--disable-detailed-tracking".equals(arg)) {
+ break;
+ case "--disable-detailed-tracking":
SystemProperties.set(PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING, "");
mBinderCallsStats.setDetailedTracking(false);
pw.println("Detailed tracking disabled");
- return;
- } else if ("--dump-worksource-provider".equals(arg)) {
+ break;
+ case "--dump-worksource-provider":
+ mBinderCallsStats.setDetailedTracking(true);
mWorkSourceProvider.dump(pw, AppIdToPackageMap.getSnapshot());
- return;
- } else if ("-h".equals(arg)) {
- pw.println("binder_calls_stats commands:");
- pw.println(" --reset: Reset stats");
- pw.println(" --enable: Enable tracking binder calls");
- pw.println(" --disable: Disables tracking binder calls");
- pw.println(" --no-sampling: Tracks all calls");
- pw.println(" --enable-detailed-tracking: Enables detailed tracking");
- pw.println(" --disable-detailed-tracking: Disables detailed tracking");
- return;
- } else {
- pw.println("Unknown option: " + arg);
- }
+ break;
+ case "--work-source-uid":
+ String uidArg = getNextArgRequired();
+ try {
+ int uid = Integer.parseInt(uidArg);
+ mBinderCallsStats.recordAllCallsForWorkSourceUid(uid);
+ } catch (NumberFormatException e) {
+ pw.println("Invalid UID: " + uidArg);
+ return -1;
+ }
+ break;
+ default:
+ return handleDefaultCommands(cmd);
}
+ return 0;
+ }
+
+ @Override
+ public void onHelp() {
+ PrintWriter pw = getOutPrintWriter();
+ pw.println("binder_calls_stats commands:");
+ pw.println(" --reset: Reset stats");
+ pw.println(" --enable: Enable tracking binder calls");
+ pw.println(" --disable: Disables tracking binder calls");
+ pw.println(" --no-sampling: Tracks all calls");
+ pw.println(" --enable-detailed-tracking: Enables detailed tracking");
+ pw.println(" --disable-detailed-tracking: Disables detailed tracking");
+ pw.println(" --work-source-uid <UID>: Track all binder calls from the UID");
}
- mBinderCallsStats.dump(pw, AppIdToPackageMap.getSnapshot(), verbose);
}
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index ef62a991f323..bd590d317910 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -4966,7 +4966,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
Slog.w(TAG, "User " + userId + " has no Vpn configuration");
return null;
}
- return vpn.getLockdownWhitelist();
+ return vpn.getLockdownAllowlist();
}
}
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 6402e07bddc3..b2f0c8376db1 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -1477,7 +1477,7 @@ public class IpSecService extends IIpSecService.Stub {
}
/**
- * Checks an IpSecConfig parcel to ensure that the contents are sane and throws an
+ * Checks an IpSecConfig parcel to ensure that the contents are valid and throws an
* IllegalArgumentException if they are not.
*/
private void checkIpSecConfig(IpSecConfig config) {
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 0ddfa1c16a0a..97f3b373f63e 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -185,10 +185,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
/** Set of interfaces with active alerts. */
@GuardedBy("mQuotaLock")
private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
- /** Set of UIDs blacklisted on metered networks. */
+ /** Set of UIDs denylisted on metered networks. */
@GuardedBy("mRulesLock")
private SparseBooleanArray mUidRejectOnMetered = new SparseBooleanArray();
- /** Set of UIDs whitelisted on metered networks. */
+ /** Set of UIDs allowlisted on metered networks. */
@GuardedBy("mRulesLock")
private SparseBooleanArray mUidAllowOnMetered = new SparseBooleanArray();
/** Set of UIDs with cleartext penalties. */
@@ -561,27 +561,27 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
synchronized (mRulesLock) {
size = mUidRejectOnMetered.size();
if (size > 0) {
- if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered blacklist rules");
+ if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered denylist rules");
uidRejectOnQuota = mUidRejectOnMetered;
mUidRejectOnMetered = new SparseBooleanArray();
}
size = mUidAllowOnMetered.size();
if (size > 0) {
- if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered whitelist rules");
+ if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered allowlist rules");
uidAcceptOnQuota = mUidAllowOnMetered;
mUidAllowOnMetered = new SparseBooleanArray();
}
}
if (uidRejectOnQuota != null) {
for (int i = 0; i < uidRejectOnQuota.size(); i++) {
- setUidMeteredNetworkBlacklist(uidRejectOnQuota.keyAt(i),
+ setUidMeteredNetworkDenylist(uidRejectOnQuota.keyAt(i),
uidRejectOnQuota.valueAt(i));
}
}
if (uidAcceptOnQuota != null) {
for (int i = 0; i < uidAcceptOnQuota.size(); i++) {
- setUidMeteredNetworkWhitelist(uidAcceptOnQuota.keyAt(i),
+ setUidMeteredNetworkAllowlist(uidAcceptOnQuota.keyAt(i),
uidAcceptOnQuota.valueAt(i));
}
}
@@ -1307,14 +1307,14 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
}
}
- private void setUidOnMeteredNetworkList(int uid, boolean blacklist, boolean enable) {
+ private void setUidOnMeteredNetworkList(int uid, boolean denylist, boolean enable) {
NetworkStack.checkNetworkStackPermission(mContext);
synchronized (mQuotaLock) {
boolean oldEnable;
SparseBooleanArray quotaList;
synchronized (mRulesLock) {
- quotaList = blacklist ? mUidRejectOnMetered : mUidAllowOnMetered;
+ quotaList = denylist ? mUidRejectOnMetered : mUidAllowOnMetered;
oldEnable = quotaList.get(uid, false);
}
if (oldEnable == enable) {
@@ -1324,7 +1324,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth");
try {
- if (blacklist) {
+ if (denylist) {
if (enable) {
mNetdService.bandwidthAddNaughtyApp(uid);
} else {
@@ -1353,12 +1353,12 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
}
@Override
- public void setUidMeteredNetworkBlacklist(int uid, boolean enable) {
+ public void setUidMeteredNetworkDenylist(int uid, boolean enable) {
setUidOnMeteredNetworkList(uid, true, enable);
}
@Override
- public void setUidMeteredNetworkWhitelist(int uid, boolean enable) {
+ public void setUidMeteredNetworkAllowlist(int uid, boolean enable) {
setUidOnMeteredNetworkList(uid, false, enable);
}
@@ -1626,7 +1626,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
}
}
}
- // Normally, whitelist chains only contain deny rules, so numUids == exemptUids.length.
+ // Normally, allowlist chains only contain deny rules, so numUids == exemptUids.length.
// But the code does not guarantee this in any way, and at least in one case - if we add
// a UID rule to the firewall, and then disable the firewall - the chains can contain
// the wrong type of rule. In this case, don't close connections that we shouldn't.
@@ -1691,7 +1691,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
// Close any sockets that were opened by the affected UIDs. This has to be done after
// disabling network connectivity, in case they react to the socket close by reopening
// the connection and race with the iptables commands that enable the firewall. All
- // whitelist and blacklist chains allow RSTs through.
+ // allowlist and denylist chains allow RSTs through.
if (enable) {
closeSocketsForFirewallChainLocked(chain, chainName);
}
@@ -1828,7 +1828,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
} else {
ruleName = "deny";
}
- } else { // Blacklist mode
+ } else { // Denylist mode
if (rule == FIREWALL_RULE_DENY) {
ruleName = "deny";
} else {
@@ -1913,8 +1913,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
pw.print("Data saver mode: "); pw.println(mDataSaverMode);
synchronized (mRulesLock) {
- dumpUidRuleOnQuotaLocked(pw, "blacklist", mUidRejectOnMetered);
- dumpUidRuleOnQuotaLocked(pw, "whitelist", mUidAllowOnMetered);
+ dumpUidRuleOnQuotaLocked(pw, "denylist", mUidRejectOnMetered);
+ dumpUidRuleOnQuotaLocked(pw, "allowlist", mUidAllowOnMetered);
}
}
@@ -2179,9 +2179,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
}
}
- void setUidOnMeteredNetworkList(boolean blacklist, int uid, boolean enable) {
+ void setUidOnMeteredNetworkList(boolean denylist, int uid, boolean enable) {
synchronized (mRulesLock) {
- if (blacklist) {
+ if (denylist) {
mUidRejectOnMetered.put(uid, enable);
} else {
mUidAllowOnMetered.put(uid, enable);
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 1689656479a5..e675d8d458c7 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -1453,8 +1453,11 @@ public class PackageWatchdog {
} else {
mHealthCheckState = HealthCheckState.ACTIVE;
}
- Slog.i(TAG, "Updated health check state for package " + getName() + ": "
- + toString(oldState) + " -> " + toString(mHealthCheckState));
+
+ if (oldState != mHealthCheckState) {
+ Slog.i(TAG, "Updated health check state for package " + getName() + ": "
+ + toString(oldState) + " -> " + toString(mHealthCheckState));
+ }
return mHealthCheckState;
}
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 59ac09ca2f3d..32d02fb17983 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -114,9 +114,6 @@ public class VibratorService extends IVibratorService.Stub
private static final VibrationAttributes DEFAULT_ATTRIBUTES =
new VibrationAttributes.Builder().build();
- // If HAL supports callbacks set the timeout to ASYNC_TIMEOUT_MULTIPLIER * duration.
- private static final long ASYNC_TIMEOUT_MULTIPLIER = 2;
-
// A mapping from the intensity adjustment to the scaling to apply, where the intensity
// adjustment is defined as the delta between the default intensity level and the user selected
// intensity level. It's important that we apply the scaling on the delta between the two so
@@ -187,8 +184,8 @@ public class VibratorService extends IVibratorService.Stub
static native int[] vibratorGetSupportedEffects(long controllerPtr);
- static native long vibratorPerformEffect(long effect, long strength, Vibration vibration,
- boolean withCallback);
+ static native long vibratorPerformEffect(
+ long controllerPtr, long effect, long strength, Vibration vibration);
static native void vibratorPerformComposedEffect(long controllerPtr,
VibrationEffect.Composition.PrimitiveEffect[] effect, Vibration vibration);
@@ -898,19 +895,11 @@ public class VibratorService extends IVibratorService.Stub
}
}
- private final Runnable mVibrationEndRunnable = new Runnable() {
- @Override
- public void run() {
- onVibrationFinished();
- }
- };
-
@GuardedBy("mLock")
private void doCancelVibrateLocked() {
Trace.asyncTraceEnd(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doCancelVibrateLocked");
try {
- mH.removeCallbacks(mVibrationEndRunnable);
if (mThread != null) {
mThread.cancel();
mThread = null;
@@ -958,13 +947,11 @@ public class VibratorService extends IVibratorService.Stub
private void startVibrationInnerLocked(Vibration vib) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationInnerLocked");
try {
- long timeout = 0;
mCurrentVibration = vib;
if (vib.effect instanceof VibrationEffect.OneShot) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.effect;
doVibratorOn(oneShot.getDuration(), oneShot.getAmplitude(), vib);
- timeout = oneShot.getDuration() * ASYNC_TIMEOUT_MULTIPLIER;
} else if (vib.effect instanceof VibrationEffect.Waveform) {
// mThread better be null here. doCancelVibrate should always be
// called before startNextVibrationLocked or startVibrationLocked.
@@ -973,24 +960,13 @@ public class VibratorService extends IVibratorService.Stub
mThread.start();
} else if (vib.effect instanceof VibrationEffect.Prebaked) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
- timeout = doVibratorPrebakedEffectLocked(vib);
+ doVibratorPrebakedEffectLocked(vib);
} else if (vib.effect instanceof VibrationEffect.Composed) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
doVibratorComposedEffectLocked(vib);
- // FIXME: We rely on the completion callback here, but I don't think we require that
- // devices which support composition also support the completion callback. If we
- // ever get a device that supports the former but not the latter, then we have no
- // real way of knowing how long a given effect should last.
- timeout = 10_000;
} else {
Slog.e(TAG, "Unknown vibration type, ignoring");
}
- // Post extra runnable to ensure vibration will end even if the HAL or native controller
- // never triggers the callback.
- // TODO: Move ASYNC_TIMEOUT_MULTIPLIER here once native controller is fully integrated.
- if (timeout > 0) {
- mH.postDelayed(mVibrationEndRunnable, timeout);
- }
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
@@ -1354,7 +1330,7 @@ public class VibratorService extends IVibratorService.Stub
}
@GuardedBy("mLock")
- private long doVibratorPrebakedEffectLocked(Vibration vib) {
+ private void doVibratorPrebakedEffectLocked(Vibration vib) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorPrebakedEffectLocked");
try {
final VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.effect;
@@ -1364,25 +1340,20 @@ public class VibratorService extends IVibratorService.Stub
}
// Input devices don't support prebaked effect, so skip trying it with them.
if (!usingInputDeviceVibrators) {
- long duration = mNativeWrapper.vibratorPerformEffect(prebaked.getId(),
- prebaked.getEffectStrength(), vib,
- hasCapability(IVibrator.CAP_PERFORM_CALLBACK));
- long timeout = duration;
- if (hasCapability(IVibrator.CAP_PERFORM_CALLBACK)) {
- timeout *= ASYNC_TIMEOUT_MULTIPLIER;
- }
- if (timeout > 0) {
+ long duration = mNativeWrapper.vibratorPerformEffect(
+ prebaked.getId(), prebaked.getEffectStrength(), vib);
+ if (duration > 0) {
noteVibratorOnLocked(vib.uid, duration);
- return timeout;
+ return;
}
}
if (!prebaked.shouldFallback()) {
- return 0;
+ return;
}
VibrationEffect effect = getFallbackEffect(prebaked.getId());
if (effect == null) {
Slog.w(TAG, "Failed to play prebaked effect, no fallback");
- return 0;
+ return;
}
Vibration fallbackVib = new Vibration(vib.token, effect, vib.attrs, vib.uid,
vib.opPkg, vib.reason + " (fallback)");
@@ -1390,7 +1361,7 @@ public class VibratorService extends IVibratorService.Stub
linkVibration(fallbackVib);
applyVibrationIntensityScalingLocked(fallbackVib, intensity);
startVibrationInnerLocked(fallbackVib);
- return 0;
+ return;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
@@ -1789,9 +1760,9 @@ public class VibratorService extends IVibratorService.Stub
}
/** Turns vibrator on to perform one of the supported effects. */
- public long vibratorPerformEffect(long effect, long strength, Vibration vibration,
- boolean withCallback) {
- return VibratorService.vibratorPerformEffect(effect, strength, vibration, withCallback);
+ public long vibratorPerformEffect(long effect, long strength, Vibration vibration) {
+ return VibratorService.vibratorPerformEffect(
+ mNativeControllerPtr, effect, strength, vibration);
}
/** Turns vibrator on to perform one of the supported composed effects. */
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 3eb26de3a675..23e9d1b552d5 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -494,6 +494,13 @@ public final class ActiveServices {
ServiceRecord r = res.record;
+ if (allowBackgroundActivityStarts) {
+ r.allowBgActivityStartsOnServiceStart();
+ }
+
+ setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, r,
+ allowBackgroundActivityStarts);
+
if (!mAm.mUserController.exists(r.userId)) {
Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId);
return null;
@@ -516,6 +523,21 @@ public final class ActiveServices {
forcedStandby = true;
}
+ if (fgRequired) {
+ if (!r.mAllowStartForeground) {
+ if (!r.mLoggedInfoAllowStartForeground) {
+ Slog.wtf(TAG, "Background started FGS " + r.mInfoAllowStartForeground);
+ r.mLoggedInfoAllowStartForeground = true;
+ }
+ if (mAm.mConstants.mFlagFgsStartRestrictionEnabled) {
+ Slog.w(TAG, "startForegroundService() not allowed due to "
+ + " mAllowStartForeground false: service "
+ + r.shortInstanceName);
+ forcedStandby = true;
+ }
+ }
+ }
+
// If this is a direct-to-foreground start, make sure it is allowed as per the app op.
boolean forceSilentAbort = false;
if (fgRequired) {
@@ -688,18 +710,7 @@ public final class ActiveServices {
"Not potential delay (user " + r.userId + " not started): " + r);
}
}
-
- if (allowBackgroundActivityStarts) {
- r.allowBgActivityStartsOnServiceStart();
- }
ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
-
- if (!r.mAllowWhileInUsePermissionInFgs) {
- r.mAllowWhileInUsePermissionInFgs =
- shouldAllowWhileInUsePermissionInFgsLocked(callingPackage, callingPid,
- callingUid, service, r, allowBackgroundActivityStarts);
- }
-
return cmp;
}
@@ -1369,6 +1380,7 @@ public final class ActiveServices {
+ r.shortInstanceName);
}
}
+
boolean alreadyStartedOp = false;
boolean stopProcStatsOp = false;
if (r.fgRequired) {
@@ -1415,6 +1427,24 @@ public final class ActiveServices {
ignoreForeground = true;
}
+ if (!ignoreForeground) {
+ if (!r.mAllowStartForeground) {
+ if (!r.mLoggedInfoAllowStartForeground) {
+ Slog.wtf(TAG, "Background started FGS "
+ + r.mInfoAllowStartForeground);
+ r.mLoggedInfoAllowStartForeground = true;
+ }
+ if (mAm.mConstants.mFlagFgsStartRestrictionEnabled) {
+ Slog.w(TAG,
+ "Service.startForeground() not allowed due to "
+ + "mAllowStartForeground false: service "
+ + r.shortInstanceName);
+ updateServiceForegroundLocked(r.app, true);
+ ignoreForeground = true;
+ }
+ }
+ }
+
// Apps under strict background restrictions simply don't get to have foreground
// services, so now that we've enforced the startForegroundService() contract
// we only do the machinery of making the service foreground when the app
@@ -2067,12 +2097,7 @@ public final class ActiveServices {
}
}
- if (!s.mAllowWhileInUsePermissionInFgs) {
- s.mAllowWhileInUsePermissionInFgs =
- shouldAllowWhileInUsePermissionInFgsLocked(callingPackage,
- callingPid, callingUid,
- service, s, false);
- }
+ setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, s, false);
if (s.app != null) {
if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
@@ -4840,21 +4865,48 @@ public final class ActiveServices {
}
/**
- * Should allow while-in-use permissions in foreground service or not.
- * while-in-use permissions in FGS started from background might be restricted.
+ * There are two FGS restrictions:
+ * In R, mAllowWhileInUsePermissionInFgs is to allow while-in-use permissions in foreground
+ * service or not. while-in-use permissions in FGS started from background might be restricted.
+ * In S, mAllowStartForeground is to allow FGS to startForeground or not. Service started
+ * from background may not become a FGS.
* @param callingPackage caller app's package name.
* @param callingUid caller app's uid.
* @param intent intent to start/bind service.
* @param r the service to start.
* @return true if allow, false otherwise.
*/
- private boolean shouldAllowWhileInUsePermissionInFgsLocked(String callingPackage,
+ private void setFgsRestrictionLocked(String callingPackage,
int callingPid, int callingUid, Intent intent, ServiceRecord r,
boolean allowBackgroundActivityStarts) {
- // Is the background FGS start restriction turned on?
+ // Check DeviceConfig flag.
if (!mAm.mConstants.mFlagBackgroundFgsStartRestrictionEnabled) {
- return true;
+ r.mAllowWhileInUsePermissionInFgs = true;
+ }
+
+ if (!r.mAllowWhileInUsePermissionInFgs || !r.mAllowStartForeground) {
+ final boolean temp = shouldAllowFgsFeatureLocked(callingPackage, callingPid,
+ callingUid, intent, r, allowBackgroundActivityStarts);
+ if (!r.mAllowWhileInUsePermissionInFgs) {
+ r.mAllowWhileInUsePermissionInFgs = temp;
+ }
+ if (!r.mAllowStartForeground) {
+ r.mAllowStartForeground = temp;
+ }
}
+ }
+
+ /**
+ * Should allow FGS feature or not.
+ * @param callingPackage caller app's package name.
+ * @param callingUid caller app's uid.
+ * @param intent intent to start/bind service.
+ * @param r the service to start.
+ * @return true if allow, false otherwise.
+ */
+ private boolean shouldAllowFgsFeatureLocked(String callingPackage,
+ int callingPid, int callingUid, Intent intent, ServiceRecord r,
+ boolean allowBackgroundActivityStarts) {
// Is the allow activity background start flag on?
if (allowBackgroundActivityStarts) {
return true;
@@ -4894,10 +4946,11 @@ public final class ActiveServices {
}
// Is the calling UID at PROCESS_STATE_TOP or above?
- final boolean isCallingUidTopApp = appIsTopLocked(callingUid);
- if (isCallingUidTopApp) {
+ final int uidState = mAm.getUidState(callingUid);
+ if (uidState <= ActivityManager.PROCESS_STATE_TOP) {
return true;
}
+
// Does the calling UID have any visible activity?
final boolean isCallingUidVisible = mAm.mAtmInternal.isUidForeground(callingUid);
if (isCallingUidVisible) {
@@ -4915,6 +4968,19 @@ public final class ActiveServices {
if (isDeviceOwner) {
return true;
}
+
+ final String info =
+ "[callingPackage: " + callingPackage
+ + "; callingUid: " + callingUid
+ + "; uidState: " + ProcessList.makeProcStateString(uidState)
+ + "; intent: " + intent
+ + "; targetSdkVersion:" + r.appInfo.targetSdkVersion
+ + "]";
+ if (!info.equals(r.mInfoAllowStartForeground)) {
+ r.mLoggedInfoAllowStartForeground = false;
+ r.mInfoAllowStartForeground = info;
+ }
+
return false;
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 775119c18037..e9539be8b0d5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -144,6 +144,13 @@ final class ActivityManagerConstants extends ContentObserver {
private static final String KEY_DEFAULT_BACKGROUND_FGS_STARTS_RESTRICTION_ENABLED =
"default_background_fgs_starts_restriction_enabled";
+ /**
+ * Default value for mFlagFgsStartRestrictionEnabled if not explicitly set in
+ * Settings.Global.
+ */
+ private static final String KEY_DEFAULT_FGS_STARTS_RESTRICTION_ENABLED =
+ "default_fgs_starts_restriction_enabled";
+
// Maximum number of cached processes we will allow.
public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
@@ -293,6 +300,11 @@ final class ActivityManagerConstants extends ContentObserver {
// started, the restriction is on while-in-use permissions.)
volatile boolean mFlagBackgroundFgsStartRestrictionEnabled = true;
+ // Indicates whether the foreground service background start restriction is enabled.
+ // When the restriction is enabled, service is not allowed to startForeground from background
+ // at all.
+ volatile boolean mFlagFgsStartRestrictionEnabled = false;
+
private final ActivityManagerService mService;
private ContentResolver mResolver;
private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -436,6 +448,9 @@ final class ActivityManagerConstants extends ContentObserver {
case KEY_DEFAULT_BACKGROUND_FGS_STARTS_RESTRICTION_ENABLED:
updateBackgroundFgsStartsRestriction();
break;
+ case KEY_DEFAULT_FGS_STARTS_RESTRICTION_ENABLED:
+ updateFgsStartsRestriction();
+ break;
case KEY_OOMADJ_UPDATE_POLICY:
updateOomAdjUpdatePolicy();
break;
@@ -659,6 +674,7 @@ final class ActivityManagerConstants extends ContentObserver {
mFlagForegroundServiceStartsLoggingEnabled = Settings.Global.getInt(mResolver,
Settings.Global.FOREGROUND_SERVICE_STARTS_LOGGING_ENABLED, 1) == 1;
}
+
private void updateBackgroundFgsStartsRestriction() {
mFlagBackgroundFgsStartRestrictionEnabled = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -666,6 +682,13 @@ final class ActivityManagerConstants extends ContentObserver {
/*defaultValue*/ true);
}
+ private void updateFgsStartsRestriction() {
+ mFlagFgsStartRestrictionEnabled = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ KEY_DEFAULT_FGS_STARTS_RESTRICTION_ENABLED,
+ /*defaultValue*/ false);
+ }
+
private void updateOomAdjUpdatePolicy() {
OOMADJ_UPDATE_QUICK = DeviceConfig.getInt(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b62ff1c26f8f..22c3b938e1ce 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1581,6 +1581,7 @@ public class ActivityManagerService extends IActivityManager.Stub
static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70;
static final int KILL_APP_ZYGOTE_MSG = 71;
static final int BINDER_HEAVYHITTER_AUTOSAMPLER_TIMEOUT_MSG = 72;
+ static final int WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG = 73;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1917,6 +1918,11 @@ public class ActivityManagerService extends IActivityManager.Stub
case BINDER_HEAVYHITTER_AUTOSAMPLER_TIMEOUT_MSG: {
handleBinderHeavyHitterAutoSamplerTimeOut();
} break;
+ case WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG: {
+ synchronized (ActivityManagerService.this) {
+ ((ContentProviderRecord) msg.obj).onProviderPublishStatusLocked(false);
+ }
+ } break;
}
}
}
@@ -4603,10 +4609,12 @@ public class ActivityManagerService extends IActivityManager.Stub
proc.lastMemInfoTime = SystemClock.uptimeMillis();
if (proc.thread != null && proc.setAdj == oomAdj) {
// Record this for posterity if the process has been stable.
- proc.baseProcessTracker.addPss(infos[i].getTotalPss(),
- infos[i].getTotalUss(), infos[i].getTotalRss(), false,
- ProcessStats.ADD_PSS_EXTERNAL_SLOW, endTime - startTime,
- proc.pkgList.mPkgList);
+ synchronized (mProcessStats.mLock) {
+ proc.baseProcessTracker.addPss(infos[i].getTotalPss(),
+ infos[i].getTotalUss(), infos[i].getTotalRss(), false,
+ ProcessStats.ADD_PSS_EXTERNAL_SLOW, endTime - startTime,
+ proc.pkgList.mPkgList);
+ }
for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) {
ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED,
@@ -4663,8 +4671,11 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
if (proc.thread != null && proc.setAdj == oomAdj) {
// Record this for posterity if the process has been stable.
- proc.baseProcessTracker.addPss(pss[i], tmpUss[0], tmpUss[2], false,
- ProcessStats.ADD_PSS_EXTERNAL, endTime-startTime, proc.pkgList.mPkgList);
+ synchronized (mProcessStats.mLock) {
+ proc.baseProcessTracker.addPss(pss[i], tmpUss[0], tmpUss[2], false,
+ ProcessStats.ADD_PSS_EXTERNAL, endTime - startTime,
+ proc.pkgList.mPkgList);
+ }
for (int ipkg = proc.pkgList.size() - 1; ipkg >= 0; ipkg--) {
ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED,
@@ -12101,8 +12112,10 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
if (r.thread != null && oomAdj == r.getSetAdjWithServices()) {
// Record this for posterity if the process has been stable.
- r.baseProcessTracker.addPss(myTotalPss, myTotalUss, myTotalRss, true,
- reportType, endTime-startTime, r.pkgList.mPkgList);
+ synchronized (mProcessStats.mLock) {
+ r.baseProcessTracker.addPss(myTotalPss, myTotalUss, myTotalRss, true,
+ reportType, endTime - startTime, r.pkgList.mPkgList);
+ }
for (int ipkg = r.pkgList.size() - 1; ipkg >= 0; ipkg--) {
ProcessStats.ProcessStateHolder holder = r.pkgList.valueAt(ipkg);
FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED,
@@ -12707,8 +12720,10 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
if (r.thread != null && oomAdj == r.getSetAdjWithServices()) {
// Record this for posterity if the process has been stable.
- r.baseProcessTracker.addPss(myTotalPss, myTotalUss, myTotalRss, true,
- reportType, endTime-startTime, r.pkgList.mPkgList);
+ synchronized (mProcessStats.mLock) {
+ r.baseProcessTracker.addPss(myTotalPss, myTotalUss, myTotalRss, true,
+ reportType, endTime - startTime, r.pkgList.mPkgList);
+ }
for (int ipkg = r.pkgList.size() - 1; ipkg >= 0; ipkg--) {
ProcessStats.ProcessStateHolder holder = r.pkgList.valueAt(ipkg);
FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED,
@@ -14470,7 +14485,7 @@ public class ActivityManagerService extends IActivityManager.Stub
resolvedType, resultTo, resultCode, resultData, resultExtras, requiredPermissions,
appOp, bOptions, ordered, sticky, callingPid, callingUid, realCallingUid,
realCallingPid, userId, false /* allowBackgroundActivityStarts */,
- null /* tokenNeededForBackgroundActivityStarts */, null /* broadcastWhitelist */);
+ null /* tokenNeededForBackgroundActivityStarts */, null /* broadcastAllowList */);
}
@GuardedBy("this")
@@ -15314,7 +15329,7 @@ public class ActivityManagerService extends IActivityManager.Stub
OP_NONE, bOptions, serialized, sticky, -1, uid, realCallingUid,
realCallingPid, userId, allowBackgroundActivityStarts,
backgroundActivityStartsToken,
- null /*broadcastWhitelist*/);
+ null /* broadcastAllowList */);
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -15921,8 +15936,10 @@ public class ActivityManagerService extends IActivityManager.Stub
EventLogTags.writeAmPss(proc.pid, proc.uid, proc.processName, pss * 1024, uss * 1024,
swapPss * 1024, rss * 1024, statType, procState, pssDuration);
proc.lastPssTime = now;
- proc.baseProcessTracker.addPss(
- pss, uss, rss, true, statType, pssDuration, proc.pkgList.mPkgList);
+ synchronized (mProcessStats.mLock) {
+ proc.baseProcessTracker.addPss(
+ pss, uss, rss, true, statType, pssDuration, proc.pkgList.mPkgList);
+ }
for (int ipkg = proc.pkgList.mPkgList.size() - 1; ipkg >= 0; ipkg--) {
ProcessStats.ProcessStateHolder holder = proc.pkgList.valueAt(ipkg);
FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_MEMORY_STAT_REPORTED,
@@ -16283,7 +16300,9 @@ public class ActivityManagerService extends IActivityManager.Stub
ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE,
ApplicationExitInfo.SUBREASON_EXCESSIVE_CPU,
true);
- app.baseProcessTracker.reportExcessiveCpu(app.pkgList.mPkgList);
+ synchronized (mProcessStats.mLock) {
+ app.baseProcessTracker.reportExcessiveCpu(app.pkgList.mPkgList);
+ }
for (int ipkg = app.pkgList.size() - 1; ipkg >= 0; ipkg--) {
ProcessStats.ProcessStateHolder holder = app.pkgList.valueAt(ipkg);
FrameworkStatsLog.write(FrameworkStatsLog.EXCESSIVE_CPU_USAGE_REPORTED,
@@ -16395,11 +16414,13 @@ public class ActivityManagerService extends IActivityManager.Stub
}
final void setProcessTrackerStateLocked(ProcessRecord proc, int memFactor, long now) {
- if (proc.thread != null && proc.baseProcessTracker != null) {
- final int procState = proc.getReportedProcState();
- if (procState != PROCESS_STATE_NONEXISTENT) {
- proc.baseProcessTracker.setState(
- procState, memFactor, now, proc.pkgList.mPkgList);
+ synchronized (mProcessStats.mLock) {
+ if (proc.thread != null && proc.baseProcessTracker != null) {
+ final int procState = proc.getReportedProcState();
+ if (procState != PROCESS_STATE_NONEXISTENT) {
+ proc.baseProcessTracker.setState(
+ procState, memFactor, now, proc.pkgList.mPkgList);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index 5cc7aba736e1..bfba4afcd4e4 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -50,6 +50,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.IBinder;
+import android.os.Message;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
@@ -218,7 +219,7 @@ public class ContentProviderHelper {
// of being published... but it is also allowed to run
// in the caller's process, so don't make a connection
// and just let the caller instantiate its own instance.
- ContentProviderHolder holder = cpr.newHolder(null);
+ ContentProviderHolder holder = cpr.newHolder(null, true);
// don't give caller the provider object, it needs to make its own.
holder.provider = null;
return holder;
@@ -415,7 +416,7 @@ public class ContentProviderHelper {
// info and allow the caller to instantiate it. Only do
// this if the provider is the same user as the caller's
// process, or can run as root (so can be in any process).
- return cpr.newHolder(null);
+ return cpr.newHolder(null, true);
}
if (ActivityManagerDebugConfig.DEBUG_PROVIDER) {
@@ -513,6 +514,38 @@ public class ContentProviderHelper {
UserHandle.getAppId(cpi.applicationInfo.uid));
}
+ if (caller != null) {
+ // The client will be waiting, and we'll notify it when the provider is ready.
+ synchronized (cpr) {
+ if (cpr.provider == null) {
+ if (cpr.launchingApp == null) {
+ Slog.w(TAG, "Unable to launch app "
+ + cpi.applicationInfo.packageName + "/"
+ + cpi.applicationInfo.uid + " for provider "
+ + name + ": launching app became null");
+ EventLogTags.writeAmProviderLostProcess(
+ UserHandle.getUserId(cpi.applicationInfo.uid),
+ cpi.applicationInfo.packageName,
+ cpi.applicationInfo.uid, name);
+ return null;
+ }
+
+ if (conn != null) {
+ conn.waiting = true;
+ }
+ Message msg = mService.mHandler.obtainMessage(
+ ActivityManagerService.WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG);
+ msg.obj = cpr;
+ mService.mHandler.sendMessageDelayed(msg,
+ ContentResolver.CONTENT_PROVIDER_READY_TIMEOUT_MILLIS);
+ }
+ }
+ // Return a holder instance even if we are waiting for the publishing of the provider,
+ // client will check for the holder.provider to see if it needs to wait for it.
+ return cpr.newHolder(conn, false);
+ }
+
+ // Because of the provider's external client (i.e., SHELL), we'll have to wait right here.
// Wait for the provider to be published...
final long timeout =
SystemClock.uptimeMillis() + ContentResolver.CONTENT_PROVIDER_READY_TIMEOUT_MILLIS;
@@ -569,7 +602,7 @@ public class ContentProviderHelper {
+ " caller=" + callerName + "/" + Binder.getCallingUid());
return null;
}
- return cpr.newHolder(conn);
+ return cpr.newHolder(conn, false);
}
void publishContentProviders(IApplicationThread caller, List<ContentProviderHolder> providers) {
@@ -622,6 +655,8 @@ public class ContentProviderHelper {
}
if (wasInLaunchingProviders) {
mService.mHandler.removeMessages(
+ ActivityManagerService.WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG, dst);
+ mService.mHandler.removeMessages(
ActivityManagerService.CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);
}
// Make sure the package is associated with the process.
@@ -635,6 +670,7 @@ public class ContentProviderHelper {
dst.provider = src.provider;
dst.setProcess(r);
dst.notifyAll();
+ dst.onProviderPublishStatusLocked(true);
}
dst.mRestartCount = 0;
mService.updateOomAdjLocked(r, true, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER);
@@ -1504,6 +1540,9 @@ public class ContentProviderHelper {
synchronized (cpr) {
cpr.launchingApp = null;
cpr.notifyAll();
+ cpr.onProviderPublishStatusLocked(false);
+ mService.mHandler.removeMessages(
+ ActivityManagerService.WAIT_FOR_CONTENT_PROVIDER_TIMEOUT_MSG, cpr);
}
final int userId = UserHandle.getUserId(cpr.uid);
// Don't remove from provider map if it doesn't match
diff --git a/services/core/java/com/android/server/am/ContentProviderRecord.java b/services/core/java/com/android/server/am/ContentProviderRecord.java
index d8d8cccc05f3..fb8b5d480b27 100644
--- a/services/core/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/core/java/com/android/server/am/ContentProviderRecord.java
@@ -85,11 +85,12 @@ final class ContentProviderRecord implements ComponentName.WithComponentName {
noReleaseNeeded = cpr.noReleaseNeeded;
}
- public ContentProviderHolder newHolder(ContentProviderConnection conn) {
+ public ContentProviderHolder newHolder(ContentProviderConnection conn, boolean local) {
ContentProviderHolder holder = new ContentProviderHolder(info);
holder.provider = provider;
holder.noReleaseNeeded = noReleaseNeeded;
holder.connection = conn;
+ holder.mLocal = local;
return holder;
}
@@ -179,6 +180,50 @@ final class ContentProviderRecord implements ComponentName.WithComponentName {
return !connections.isEmpty() || hasExternalProcessHandles();
}
+ /**
+ * Notify all clients that the provider has been published and ready to use,
+ * or timed out.
+ *
+ * @param status true: successfully published; false: timed out
+ */
+ void onProviderPublishStatusLocked(boolean status) {
+ final int numOfConns = connections.size();
+ final int userId = UserHandle.getUserId(appInfo.uid);
+ for (int i = 0; i < numOfConns; i++) {
+ final ContentProviderConnection conn = connections.get(i);
+ if (conn.waiting && conn.client != null) {
+ final ProcessRecord client = conn.client;
+ if (!status) {
+ if (launchingApp == null) {
+ Slog.w(TAG_AM, "Unable to launch app "
+ + appInfo.packageName + "/"
+ + appInfo.uid + " for provider "
+ + info.authority + ": launching app became null");
+ EventLogTags.writeAmProviderLostProcess(
+ userId,
+ appInfo.packageName,
+ appInfo.uid, info.authority);
+ } else {
+ Slog.wtf(TAG_AM, "Timeout waiting for provider "
+ + appInfo.packageName + "/"
+ + appInfo.uid + " for provider "
+ + info.authority
+ + " caller=" + client);
+ }
+ }
+ if (client.thread != null) {
+ try {
+ client.thread.notifyContentProviderPublishStatus(
+ newHolder(status ? conn : null, false),
+ info.authority, userId, status);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ conn.waiting = false;
+ }
+ }
+
void dump(PrintWriter pw, String prefix, boolean full) {
if (full) {
pw.print(prefix); pw.print("package=");
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index e3e13391a8b0..14bc6cbed7d7 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1079,8 +1079,8 @@ class ProcessRecord implements WindowProcessListener {
*/
public void resetPackageList(ProcessStatsService tracker) {
final int N = pkgList.size();
- if (baseProcessTracker != null) {
- synchronized (tracker.mLock) {
+ synchronized (tracker.mLock) {
+ if (baseProcessTracker != null) {
long now = SystemClock.uptimeMillis();
baseProcessTracker.setState(ProcessStats.STATE_NOTHING,
tracker.getMemFactorLocked(), now, pkgList.mPkgList);
@@ -1108,10 +1108,11 @@ class ProcessRecord implements WindowProcessListener {
holder.state.makeActive();
}
}
+ } else if (N != 1) {
+ pkgList.clear();
+ pkgList.put(info.packageName,
+ new ProcessStats.ProcessStateHolder(info.longVersionCode));
}
- } else if (N != 1) {
- pkgList.clear();
- pkgList.put(info.packageName, new ProcessStats.ProcessStateHolder(info.longVersionCode));
}
}
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 4a2703056871..66677b67b6aa 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -146,6 +146,12 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
// the most recent package that start/bind this service.
String mRecentCallingPackage;
+ // allow the service becomes foreground service? Service started from background may not be
+ // allowed to become a foreground service.
+ boolean mAllowStartForeground;
+ String mInfoAllowStartForeground;
+ boolean mLoggedInfoAllowStartForeground;
+
String stringName; // caching of toString
private int lastStartId; // identifier of most recent start request.
@@ -408,6 +414,10 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
pw.println(mAllowWhileInUsePermissionInFgs);
pw.print(prefix); pw.print("recentCallingPackage=");
pw.println(mRecentCallingPackage);
+ pw.print(prefix); pw.print("allowStartForeground=");
+ pw.println(mAllowStartForeground);
+ pw.print(prefix); pw.print("infoAllowStartForeground=");
+ pw.println(mInfoAllowStartForeground);
if (delayed) {
pw.print(prefix); pw.print("delayed="); pw.println(delayed);
}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 0658e8139cc2..7420e0a6e828 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -1630,7 +1630,7 @@ class UserController implements Handler.Callback {
UserInfo currentUserInfo = getUserInfo(currentUserId);
Pair<UserInfo, UserInfo> userNames = new Pair<>(currentUserInfo, targetUserInfo);
mUiHandler.removeMessages(START_USER_SWITCH_UI_MSG);
- mUiHandler.sendMessage(mHandler.obtainMessage(
+ mUiHandler.sendMessage(mUiHandler.obtainMessage(
START_USER_SWITCH_UI_MSG, userNames));
} else {
mHandler.removeMessages(START_USER_SWITCH_FG_MSG);
@@ -2887,13 +2887,18 @@ class UserController implements Handler.Callback {
void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser,
String switchingFromSystemUserMessage, String switchingToSystemUserMessage) {
- if (!mService.mContext.getPackageManager()
+ if (mService.mContext.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
- final Dialog d = new UserSwitchingDialog(mService, mService.mContext, fromUser,
- toUser, true /* above system */, switchingFromSystemUserMessage,
- switchingToSystemUserMessage);
- d.show();
- }
+ // config_customUserSwitchUi is set to true on Automotive as CarSystemUI is
+ // responsible to show the UI; OEMs should not change that, but if they do, we
+ // should at least warn the user...
+ Slog.w(TAG, "Showing user switch dialog on UserController, it could cause a race "
+ + "condition if it's shown by CarSystemUI as well");
+ }
+ final Dialog d = new UserSwitchingDialog(mService, mService.mContext, fromUser,
+ toUser, true /* above system */, switchingFromSystemUserMessage,
+ switchingToSystemUserMessage);
+ d.show();
}
void reportGlobalUsageEventLocked(int event) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 0a179e89f757..bf7c68a845c5 100755
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1283,7 +1283,6 @@ public class AudioService extends IAudioService.Stub
}
if (isPlatformTelevision()) {
- checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI, caller);
synchronized (mHdmiClientLock) {
if (mHdmiManager != null && mHdmiPlaybackClient != null) {
updateHdmiCecSinkLocked(mHdmiCecSink | false);
@@ -1303,22 +1302,54 @@ public class AudioService extends IAudioService.Stub
}
}
- private void checkAddAllFixedVolumeDevices(int device, String caller) {
+ /**
+ * Update volume states for the given device.
+ *
+ * This will initialize the volume index if no volume index is available.
+ * If the device is the currently routed device, fixed/full volume policies will be applied.
+ *
+ * @param device a single audio device, ensure that this is not a devices bitmask
+ * @param caller caller of this method
+ */
+ private void updateVolumeStatesForAudioDevice(int device, String caller) {
final int numStreamTypes = AudioSystem.getNumStreamTypes();
for (int streamType = 0; streamType < numStreamTypes; streamType++) {
- if (!mStreamStates[streamType].hasIndexForDevice(device)) {
- // set the default value, if device is affected by a full/fix/abs volume rule, it
- // will taken into account in checkFixedVolumeDevices()
- mStreamStates[streamType].setIndex(
- mStreamStates[mStreamVolumeAlias[streamType]]
- .getIndex(AudioSystem.DEVICE_OUT_DEFAULT),
- device, caller, true /*hasModifyAudioSettings*/);
- }
- mStreamStates[streamType].checkFixedVolumeDevices();
+ updateVolumeStates(device, streamType, caller);
+ }
+ }
- // Unmute streams if device is full volume
- if (mFullVolumeDevices.contains(device)) {
- mStreamStates[streamType].mute(false);
+ /**
+ * Update volume states for the given device and given stream.
+ *
+ * This will initialize the volume index if no volume index is available.
+ * If the device is the currently routed device, fixed/full volume policies will be applied.
+ *
+ * @param device a single audio device, ensure that this is not a devices bitmask
+ * @param streamType streamType to be updated
+ * @param caller caller of this method
+ */
+ private void updateVolumeStates(int device, int streamType, String caller) {
+ if (!mStreamStates[streamType].hasIndexForDevice(device)) {
+ // set the default value, if device is affected by a full/fix/abs volume rule, it
+ // will taken into account in checkFixedVolumeDevices()
+ mStreamStates[streamType].setIndex(
+ mStreamStates[mStreamVolumeAlias[streamType]]
+ .getIndex(AudioSystem.DEVICE_OUT_DEFAULT),
+ device, caller, true /*hasModifyAudioSettings*/);
+ }
+
+ // Check if device to be updated is routed for the given audio stream
+ List<AudioDeviceAttributes> devicesForAttributes = getDevicesForAttributesInt(
+ new AudioAttributes.Builder().setInternalLegacyStreamType(streamType).build());
+ for (AudioDeviceAttributes deviceAttributes : devicesForAttributes) {
+ if (deviceAttributes.getType() == AudioDeviceInfo.convertInternalDeviceToDeviceType(
+ device)) {
+ mStreamStates[streamType].checkFixedVolumeDevices();
+
+ // Unmute streams if required if device is full volume
+ if (isStreamMute(streamType) && mFullVolumeDevices.contains(device)) {
+ mStreamStates[streamType].mute(false);
+ }
}
}
}
@@ -1868,8 +1899,13 @@ public class AudioService extends IAudioService.Stub
/** @see AudioManager#getDevicesForAttributes(AudioAttributes) */
public @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributes(
@NonNull AudioAttributes attributes) {
- Objects.requireNonNull(attributes);
enforceModifyAudioRoutingPermission();
+ return getDevicesForAttributesInt(attributes);
+ }
+
+ protected @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributesInt(
+ @NonNull AudioAttributes attributes) {
+ Objects.requireNonNull(attributes);
return AudioSystem.getDevicesForAttributes(attributes);
}
@@ -4916,7 +4952,15 @@ public class AudioService extends IAudioService.Stub
synchronized (VolumeStreamState.class) {
for (int stream = 0; stream < mStreamStates.length; stream++) {
if (stream != skipStream) {
- mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/);
+ int devices = mStreamStates[stream].observeDevicesForStream_syncVSS(
+ false /*checkOthers*/);
+
+ Set<Integer> devicesSet = AudioSystem.generateAudioDeviceTypesSet(devices);
+ for (Integer device : devicesSet) {
+ // Update volume states for devices routed for the stream
+ updateVolumeStates(device, stream,
+ "AudioService#observeDevicesForStreams");
+ }
}
}
}
@@ -4985,7 +5029,7 @@ public class AudioService extends IAudioService.Stub
+ Integer.toHexString(audioSystemDeviceOut) + " from:" + caller));
// make sure we have a volume entry for this device, and that volume is updated according
// to volume behavior
- checkAddAllFixedVolumeDevices(audioSystemDeviceOut, "setDeviceVolumeBehavior:" + caller);
+ updateVolumeStatesForAudioDevice(audioSystemDeviceOut, "setDeviceVolumeBehavior:" + caller);
}
/**
@@ -7207,10 +7251,9 @@ public class AudioService extends IAudioService.Stub
// HDMI output
removeAudioSystemDeviceOutFromFullVolumeDevices(AudioSystem.DEVICE_OUT_HDMI);
}
+ updateVolumeStatesForAudioDevice(AudioSystem.DEVICE_OUT_HDMI,
+ "HdmiPlaybackClient.DisplayStatusCallback");
}
-
- checkAddAllFixedVolumeDevices(AudioSystem.DEVICE_OUT_HDMI,
- "HdmiPlaybackClient.DisplayStatusCallback");
}
private class MyHdmiControlStatusChangeListenerCallback
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index 7202f0f401f9..7f9b3c9fcff7 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -56,7 +56,6 @@ import android.system.OsConstants;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
-import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -130,7 +129,42 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
}
}
- public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd) {
+ /**
+ * A data class to store each uid Netd permission information. Netd permissions includes
+ * PERMISSION_NETWORK, PERMISSION_SYSTEM, PERMISSION_INTERNET, PERMISSION_UPDATE_DEVICE_STATS
+ * and OR'd with the others. Default permission is PERMISSION_NONE and PERMISSION_UNINSTALLED
+ * will be set if all packages are removed from the uid.
+ */
+ public static class UidNetdPermissionInfo {
+ private final int mNetdPermissions;
+
+ UidNetdPermissionInfo() {
+ this(PERMISSION_NONE);
+ }
+
+ UidNetdPermissionInfo(int permissions) {
+ mNetdPermissions = permissions;
+ }
+
+ /** Plus given permissions and return new UidNetdPermissionInfo instance. */
+ public UidNetdPermissionInfo plusNetdPermissions(int permissions) {
+ return new UidNetdPermissionInfo(mNetdPermissions | permissions);
+ }
+
+ /** Return whether package is uninstalled. */
+ public boolean isPackageUninstalled() {
+ return mNetdPermissions == PERMISSION_UNINSTALLED;
+ }
+
+ /** Check that uid has given permissions */
+ public boolean hasNetdPermissions(final int permissions) {
+ if (isPackageUninstalled()) return false;
+ if (permissions == PERMISSION_NONE) return true;
+ return (mNetdPermissions & permissions) == permissions;
+ }
+ }
+
+ public PermissionMonitor(Context context, INetd netd) {
this(context, netd, new Dependencies());
}
@@ -161,7 +195,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
return;
}
- SparseIntArray netdPermsUids = new SparseIntArray();
+ final SparseArray<UidNetdPermissionInfo> netdPermsUids = new SparseArray<>();
for (PackageInfo app : apps) {
int uid = app.applicationInfo != null ? app.applicationInfo.uid : INVALID_UID;
@@ -183,9 +217,13 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
}
}
+ // Skip already checked uid.
+ if (netdPermsUids.get(uid) != null) continue;
+
//TODO: unify the management of the permissions into one codepath.
- final int otherNetdPerms = getNetdPermissionMask(uid);
- netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms);
+ final UidNetdPermissionInfo permInfo =
+ new UidNetdPermissionInfo(getNetdPermissionMask(uid));
+ netdPermsUids.put(uid, permInfo);
}
List<UserInfo> users = mUserManager.getUsers(true); // exclude dying users
@@ -207,7 +245,10 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
? PERMISSION_UPDATE_DEVICE_STATS : 0;
netdPermission |= perms.contains(INTERNET) ? PERMISSION_INTERNET : 0;
}
- netdPermsUids.put(uid, netdPermsUids.get(uid) | netdPermission);
+ final UidNetdPermissionInfo permInfo = netdPermsUids.get(uid);
+ netdPermsUids.put(uid, permInfo != null
+ ? permInfo.plusNetdPermissions(netdPermission)
+ : new UidNetdPermissionInfo(netdPermission));
}
log("Users: " + mUsers.size() + ", Apps: " + mApps.size());
update(mUsers, mApps, true);
@@ -341,15 +382,15 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
return currentPermission;
}
- private int getPermissionForUid(final int uid) {
+ private UidNetdPermissionInfo getPermissionForUid(final int uid) {
// Check all the packages for this UID. The UID has the permission if any of the
// packages in it has the permission.
final String[] packages = mPackageManager.getPackagesForUid(uid);
if (packages == null || packages.length <= 0) {
// The last package of this uid is removed from device. Clean the package up.
- return PERMISSION_UNINSTALLED;
+ return new UidNetdPermissionInfo(PERMISSION_UNINSTALLED);
}
- return getNetdPermissionMask(uid);
+ return new UidNetdPermissionInfo(getNetdPermissionMask(uid));
}
/**
@@ -599,28 +640,28 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
* permission information to netd.
*
* @param uid the app uid of the package installed
- * @param permissions the permissions the app requested and netd cares about.
+ * @param permissionInfo the permission info of given uid.
*
* @hide
*/
@VisibleForTesting
- void sendPackagePermissionsForUid(int uid, int permissions) {
- SparseIntArray netdPermissionsAppIds = new SparseIntArray();
- netdPermissionsAppIds.put(uid, permissions);
- sendPackagePermissionsToNetd(netdPermissionsAppIds);
+ void sendPackagePermissionsForUid(int uid, UidNetdPermissionInfo permissionInfo) {
+ final SparseArray<UidNetdPermissionInfo> uidsPermInfo = new SparseArray<>();
+ uidsPermInfo.put(uid, permissionInfo);
+ sendPackagePermissionsToNetd(uidsPermInfo);
}
/**
* Called by packageManagerService to send IPC to netd. Grant or revoke the INTERNET
* and/or UPDATE_DEVICE_STATS permission of the uids in array.
*
- * @param netdPermissionsAppIds integer pairs of uids and the permission granted to it. If the
- * permission is 0, revoke all permissions of that uid.
- *
+ * @param uidsPermInfo permission info array generated from each uid. If the uid permission is
+ * PERMISSION_NONE or PERMISSION_UNINSTALLED, revoke all permissions of that
+ * uid.
* @hide
*/
@VisibleForTesting
- void sendPackagePermissionsToNetd(SparseIntArray netdPermissionsAppIds) {
+ void sendPackagePermissionsToNetd(final SparseArray<UidNetdPermissionInfo> uidsPermInfo) {
if (mNetd == null) {
Log.e(TAG, "Failed to get the netd service");
return;
@@ -630,26 +671,20 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
ArrayList<Integer> updateStatsPermissionAppIds = new ArrayList<>();
ArrayList<Integer> noPermissionAppIds = new ArrayList<>();
ArrayList<Integer> uninstalledAppIds = new ArrayList<>();
- for (int i = 0; i < netdPermissionsAppIds.size(); i++) {
- int permissions = netdPermissionsAppIds.valueAt(i);
- switch(permissions) {
- case (PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS):
- allPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
- break;
- case PERMISSION_INTERNET:
- internetPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
- break;
- case PERMISSION_UPDATE_DEVICE_STATS:
- updateStatsPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
- break;
- case PERMISSION_NONE:
- noPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
- break;
- case PERMISSION_UNINSTALLED:
- uninstalledAppIds.add(netdPermissionsAppIds.keyAt(i));
- default:
- Log.e(TAG, "unknown permission type: " + permissions + "for uid: "
- + netdPermissionsAppIds.keyAt(i));
+ for (int i = 0; i < uidsPermInfo.size(); i++) {
+ final int uid = uidsPermInfo.keyAt(i);
+ final UidNetdPermissionInfo permInfo = uidsPermInfo.valueAt(i);
+ if (permInfo.hasNetdPermissions(
+ PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS)) {
+ allPermissionAppIds.add(uid);
+ } else if (permInfo.hasNetdPermissions(PERMISSION_INTERNET)) {
+ internetPermissionAppIds.add(uid);
+ } else if (permInfo.hasNetdPermissions(PERMISSION_UPDATE_DEVICE_STATS)) {
+ updateStatsPermissionAppIds.add(uid);
+ } else if (permInfo.isPackageUninstalled()) {
+ uninstalledAppIds.add(uid);
+ } else {
+ noPermissionAppIds.add(uid);
}
}
try {
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 1c93d4eb599b..5484bfca5851 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -153,8 +153,8 @@ public class Vpn {
private static final boolean LOGD = true;
// Length of time (in milliseconds) that an app hosting an always-on VPN is placed on
- // the device idle whitelist during service launch and VPN bootstrap.
- private static final long VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS = 60 * 1000;
+ // the device idle allowlist during service launch and VPN bootstrap.
+ private static final long VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS = 60 * 1000;
// Settings for how much of the address space should be routed so that Vpn considers
// "most" of the address space is routed. This is used to determine whether this Vpn
@@ -180,7 +180,8 @@ public class Vpn {
// This is taken as a total of IPv4 + IPV6 routes for simplicity, but the algorithm
// is actually O(n²)+O(n²).
private static final int MAX_ROUTES_TO_EVALUATE = 150;
-
+ private static final String LOCKDOWN_ALLOWLIST_SETTING_NAME =
+ Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST;
/**
* Largest profile size allowable for Platform VPNs.
*
@@ -236,7 +237,7 @@ public class Vpn {
* Set of packages in addition to the VPN app itself that can access the network directly when
* VPN is not connected even if {@code mLockdown} is set.
*/
- private @NonNull List<String> mLockdownWhitelist = Collections.emptyList();
+ private @NonNull List<String> mLockdownAllowlist = Collections.emptyList();
/**
* A memory of what UIDs this class told netd to block for the lockdown feature.
@@ -520,7 +521,7 @@ public class Vpn {
}
}
if (!hadUnderlyingNetworks) {
- // No idea what the underlying networks are; assume sane defaults
+ // No idea what the underlying networks are; assume the safer defaults
metered = true;
roaming = false;
congested = false;
@@ -653,18 +654,18 @@ public class Vpn {
*
* @param packageName the package to designate as always-on VPN supplier.
* @param lockdown whether to prevent traffic outside of a VPN, for example while connecting.
- * @param lockdownWhitelist packages to be whitelisted from lockdown.
+ * @param lockdownAllowlist packages to be allowed from lockdown.
* @param keyStore the Keystore instance to use for checking of PlatformVpnProfile(s)
* @return {@code true} if the package has been set as always-on, {@code false} otherwise.
*/
public synchronized boolean setAlwaysOnPackage(
@Nullable String packageName,
boolean lockdown,
- @Nullable List<String> lockdownWhitelist,
+ @Nullable List<String> lockdownAllowlist,
@NonNull KeyStore keyStore) {
enforceControlPermissionOrInternalCaller();
- if (setAlwaysOnPackageInternal(packageName, lockdown, lockdownWhitelist, keyStore)) {
+ if (setAlwaysOnPackageInternal(packageName, lockdown, lockdownAllowlist, keyStore)) {
saveAlwaysOnPackage();
return true;
}
@@ -679,7 +680,7 @@ public class Vpn {
*
* @param packageName the package to designate as always-on VPN supplier.
* @param lockdown whether to prevent traffic outside of a VPN, for example while connecting.
- * @param lockdownWhitelist packages to be whitelisted from lockdown. This is only used if
+ * @param lockdownAllowlist packages to be allowed to bypass lockdown. This is only used if
* {@code lockdown} is {@code true}. Packages must not contain commas.
* @param keyStore the system keystore instance to check for profiles
* @return {@code true} if the package has been set as always-on, {@code false} otherwise.
@@ -687,16 +688,16 @@ public class Vpn {
@GuardedBy("this")
private boolean setAlwaysOnPackageInternal(
@Nullable String packageName, boolean lockdown,
- @Nullable List<String> lockdownWhitelist, @NonNull KeyStore keyStore) {
+ @Nullable List<String> lockdownAllowlist, @NonNull KeyStore keyStore) {
if (VpnConfig.LEGACY_VPN.equals(packageName)) {
Log.w(TAG, "Not setting legacy VPN \"" + packageName + "\" as always-on.");
return false;
}
- if (lockdownWhitelist != null) {
- for (String pkg : lockdownWhitelist) {
+ if (lockdownAllowlist != null) {
+ for (String pkg : lockdownAllowlist) {
if (pkg.contains(",")) {
- Log.w(TAG, "Not setting always-on vpn, invalid whitelisted package: " + pkg);
+ Log.w(TAG, "Not setting always-on vpn, invalid allowed package: " + pkg);
return false;
}
}
@@ -724,8 +725,8 @@ public class Vpn {
}
mLockdown = (mAlwaysOn && lockdown);
- mLockdownWhitelist = (mLockdown && lockdownWhitelist != null)
- ? Collections.unmodifiableList(new ArrayList<>(lockdownWhitelist))
+ mLockdownAllowlist = (mLockdown && lockdownAllowlist != null)
+ ? Collections.unmodifiableList(new ArrayList<>(lockdownAllowlist))
: Collections.emptyList();
if (isCurrentPreparedPackage(packageName)) {
@@ -754,10 +755,10 @@ public class Vpn {
}
/**
- * @return an immutable list of packages whitelisted from always-on VPN lockdown.
+ * @return an immutable list of packages allowed to bypass always-on VPN lockdown.
*/
- public synchronized List<String> getLockdownWhitelist() {
- return mLockdown ? mLockdownWhitelist : null;
+ public synchronized List<String> getLockdownAllowlist() {
+ return mLockdown ? mLockdownAllowlist : null;
}
/**
@@ -772,8 +773,8 @@ public class Vpn {
mSystemServices.settingsSecurePutIntForUser(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN,
(mAlwaysOn && mLockdown ? 1 : 0), mUserHandle);
mSystemServices.settingsSecurePutStringForUser(
- Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST,
- String.join(",", mLockdownWhitelist), mUserHandle);
+ LOCKDOWN_ALLOWLIST_SETTING_NAME,
+ String.join(",", mLockdownAllowlist), mUserHandle);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -788,12 +789,12 @@ public class Vpn {
Settings.Secure.ALWAYS_ON_VPN_APP, mUserHandle);
final boolean alwaysOnLockdown = mSystemServices.settingsSecureGetIntForUser(
Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, 0 /*default*/, mUserHandle) != 0;
- final String whitelistString = mSystemServices.settingsSecureGetStringForUser(
- Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST, mUserHandle);
- final List<String> whitelistedPackages = TextUtils.isEmpty(whitelistString)
- ? Collections.emptyList() : Arrays.asList(whitelistString.split(","));
+ final String allowlistString = mSystemServices.settingsSecureGetStringForUser(
+ LOCKDOWN_ALLOWLIST_SETTING_NAME, mUserHandle);
+ final List<String> allowedPackages = TextUtils.isEmpty(allowlistString)
+ ? Collections.emptyList() : Arrays.asList(allowlistString.split(","));
setAlwaysOnPackageInternal(
- alwaysOnPackage, alwaysOnLockdown, whitelistedPackages, keyStore);
+ alwaysOnPackage, alwaysOnLockdown, allowedPackages, keyStore);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -849,7 +850,7 @@ public class Vpn {
DeviceIdleInternal idleController =
LocalServices.getService(DeviceIdleInternal.class);
idleController.addPowerSaveTempWhitelistApp(Process.myUid(), alwaysOnPackage,
- VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS, mUserHandle, false, "vpn");
+ VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS, mUserHandle, false, "vpn");
// Start the VPN service declared in the app's manifest.
Intent serviceIntent = new Intent(VpnConfig.SERVICE_INTERFACE);
@@ -1212,7 +1213,7 @@ public class Vpn {
// applications have changed. Consider diffing UID ranges and only applying the delta.
if (!Objects.equals(oldConfig.allowedApplications, mConfig.allowedApplications) ||
!Objects.equals(oldConfig.disallowedApplications, mConfig.disallowedApplications)) {
- Log.i(TAG, "Handover not possible due to changes to whitelisted/blacklisted apps");
+ Log.i(TAG, "Handover not possible due to changes to allowed/denied apps");
return false;
}
@@ -1440,13 +1441,13 @@ public class Vpn {
* associated with one user, and any restricted profiles attached to that user.
*
* <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided,
- * the UID ranges will match the app whitelist or blacklist specified there. Otherwise, all UIDs
+ * the UID ranges will match the app list specified there. Otherwise, all UIDs
* in each user and profile will be included.
*
* @param userHandle The userId to create UID ranges for along with any of its restricted
* profiles.
- * @param allowedApplications (optional) whitelist of applications to include.
- * @param disallowedApplications (optional) blacklist of applications to exclude.
+ * @param allowedApplications (optional) List of applications to allow.
+ * @param disallowedApplications (optional) List of applications to deny.
*/
@VisibleForTesting
Set<UidRange> createUserAndRestrictedProfilesRanges(@UserIdInt int userHandle,
@@ -1480,13 +1481,13 @@ public class Vpn {
* associated with one user.
*
* <p>If one of {@param allowedApplications} or {@param disallowedApplications} is provided,
- * the UID ranges will match the app whitelist or blacklist specified there. Otherwise, all UIDs
+ * the UID ranges will match the app allowlist or denylist specified there. Otherwise, all UIDs
* in the user will be included.
*
* @param ranges {@link Set} of {@link UidRange}s to which to add.
* @param userHandle The userId to add to {@param ranges}.
- * @param allowedApplications (optional) whitelist of applications to include.
- * @param disallowedApplications (optional) blacklist of applications to exclude.
+ * @param allowedApplications (optional) allowlist of applications to include.
+ * @param disallowedApplications (optional) denylist of applications to exclude.
*/
@VisibleForTesting
void addUserToRanges(@NonNull Set<UidRange> ranges, @UserIdInt int userHandle,
@@ -1608,7 +1609,7 @@ public class Vpn {
/**
* Restricts network access from all UIDs affected by this {@link Vpn}, apart from the VPN
- * service app itself and whitelisted packages, to only sockets that have had {@code protect()}
+ * service app itself and allowed packages, to only sockets that have had {@code protect()}
* called on them. All non-VPN traffic is blocked via a {@code PROHIBIT} response from the
* kernel.
*
@@ -1630,7 +1631,7 @@ public class Vpn {
if (isNullOrLegacyVpn(mPackage)) {
exemptedPackages = null;
} else {
- exemptedPackages = new ArrayList<>(mLockdownWhitelist);
+ exemptedPackages = new ArrayList<>(mLockdownAllowlist);
exemptedPackages.add(mPackage);
}
final Set<UidRange> rangesToTellNetdToRemove = new ArraySet<>(mBlockedUidsAsToldToNetd);
@@ -1675,7 +1676,7 @@ public class Vpn {
* Tell netd to add or remove a list of {@link UidRange}s to the list of UIDs that are only
* allowed to make connections through sockets that have had {@code protect()} called on them.
*
- * @param enforce {@code true} to add to the blacklist, {@code false} to remove.
+ * @param enforce {@code true} to add to the denylist, {@code false} to remove.
* @param ranges {@link Collection} of {@link UidRange}s to add (if {@param enforce} is
* {@code true}) or to remove.
* @return {@code true} if all of the UIDs were added/removed. {@code false} otherwise,
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 397358b44362..dab8c7fc9d48 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -30,8 +30,6 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUST
import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL;
-import static android.view.Surface.ROTATION_270;
-import static android.view.Surface.ROTATION_90;
import android.Manifest;
import android.annotation.NonNull;
@@ -46,7 +44,6 @@ import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.graphics.ColorSpace;
import android.graphics.Point;
-import android.graphics.Rect;
import android.hardware.SensorManager;
import android.hardware.display.AmbientBrightnessDayStats;
import android.hardware.display.BrightnessChangeEvent;
@@ -104,7 +101,6 @@ import com.android.server.AnimationThread;
import com.android.server.DisplayThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
import com.android.server.UiThread;
import com.android.server.wm.SurfaceAnimationThread;
import com.android.server.wm.WindowManagerInternal;
@@ -1394,9 +1390,13 @@ public final class DisplayManagerService extends SystemService {
}
final DisplayInfo displayInfo = logicalDisplay.getDisplayInfoLocked();
- return SurfaceControl.screenshotToBufferWithSecureLayersUnsafe(token, new Rect(),
- displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight(),
- false /* useIdentityTransform */, 0 /* rotation */);
+ final SurfaceControl.DisplayCaptureArgs captureArgs =
+ new SurfaceControl.DisplayCaptureArgs.Builder(token)
+ .setSize(displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight())
+ .setUseIdentityTransform(true)
+ .setCaptureSecureLayers(true)
+ .build();
+ return SurfaceControl.captureDisplay(captureArgs);
}
}
@@ -1406,30 +1406,11 @@ public final class DisplayManagerService extends SystemService {
if (token == null) {
return null;
}
- final LogicalDisplay logicalDisplay = mLogicalDisplays.get(displayId);
- if (logicalDisplay == null) {
- return null;
- }
-
- final DisplayInfo displayInfo = logicalDisplay.getDisplayInfoLocked();
- // Takes screenshot based on current device orientation.
- final Display display = DisplayManagerGlobal.getInstance()
- .getRealDisplay(displayId);
- if (display == null) {
- return null;
- }
- final Point displaySize = new Point();
- display.getRealSize(displaySize);
-
- int rotation = displayInfo.rotation;
- // TODO (b/153382624) : This workaround solution would be removed after
- // SurfaceFlinger fixes the inconsistency with rotation direction issue.
- if (rotation == ROTATION_90 || rotation == ROTATION_270) {
- rotation = (rotation == ROTATION_90) ? ROTATION_270 : ROTATION_90;
- }
- return SurfaceControl.screenshotToBuffer(token, new Rect(), displaySize.x,
- displaySize.y, false /* useIdentityTransform */, rotation /* rotation */);
+ final SurfaceControl.DisplayCaptureArgs captureArgs =
+ new SurfaceControl.DisplayCaptureArgs.Builder(token)
+ .build();
+ return SurfaceControl.captureDisplay(captureArgs);
}
}
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index 7bbcdaa2d473..6672daa6f17a 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -949,7 +949,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
if (debug) {
Slog.d(mTag, "Eagerly recreating service for user " + userId);
}
- getServiceForUserLocked(userId);
+ updateCachedServiceLocked(userId);
}
}
onServicePackageRestartedLocked(userId);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
index 05cf40a091b6..3ac95d71de3d 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
@@ -178,7 +178,7 @@ public abstract class InputMethodManagerInternal {
};
/**
- * @return Global instance if exists. Otherwise, a dummy no-op instance.
+ * @return Global instance if exists. Otherwise, a fallback no-op instance.
*/
@NonNull
public static InputMethodManagerInternal get() {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 3cd70fecbf3d..85a4515d46a0 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2213,8 +2213,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
* @param client {@link android.os.Binder} proxy that is associated with the singleton instance
* of {@link android.view.inputmethod.InputMethodManager} that runs on the client
* process
- * @param inputContext communication channel for the dummy
- * {@link android.view.inputmethod.InputConnection}
+ * @param inputContext communication channel for the fallback {@link InputConnection}
* @param selfReportedDisplayId self-reported display ID to which the client is associated.
* Whether the client is still allowed to access to this display
* or not needs to be evaluated every time the client interacts
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index 937514ca9139..b518eb1ab6d0 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -1663,7 +1663,7 @@ public final class MultiClientInputMethodManagerService {
}
if (editorInfo == null) {
- // So-called dummy InputConnection scenario. For app compatibility, we still
+ // So-called fallback InputConnection scenario. For app compatibility, we still
// notify this to the IME.
switch (clientInfo.mState) {
case InputMethodClientState.READY_TO_SEND_FIRST_BIND_RESULT:
diff --git a/services/core/java/com/android/server/location/LocationProviderManager.java b/services/core/java/com/android/server/location/LocationProviderManager.java
index d4f8c7e855b9..c3532a84c42d 100644
--- a/services/core/java/com/android/server/location/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/LocationProviderManager.java
@@ -1615,7 +1615,7 @@ class LocationProviderManager extends
case LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF:
// fall through
case LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF:
- updateService();
+ updateRegistrations(registration -> true);
break;
default:
break;
diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
index 8004ec70aaf3..850cf7f4b7ce 100644
--- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
@@ -49,8 +49,6 @@ import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.PowerManager;
-import android.os.PowerManager.ServiceType;
-import android.os.PowerSaveState;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -486,10 +484,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
deviceIdleService.unregisterStationaryListener(
mDeviceIdleStationaryListener);
}
- // Intentional fall-through.
- case PowerManager.ACTION_POWER_SAVE_MODE_CHANGED:
- case Intent.ACTION_SCREEN_OFF:
- case Intent.ACTION_SCREEN_ON:
// Call updateLowPowerMode on handler thread so it's always called from the
// same thread.
mHandler.sendEmptyMessage(UPDATE_LOW_POWER_MODE);
@@ -554,15 +548,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
private void updateLowPowerMode() {
// Disable GPS if we are in device idle mode and the device is stationary.
boolean disableGpsForPowerManager = mPowerManager.isDeviceIdleMode() && mIsDeviceStationary;
- final PowerSaveState result = mPowerManager.getPowerSaveState(ServiceType.LOCATION);
- switch (result.locationMode) {
- case PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF:
- case PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF:
- // If we are in battery saver mode and the screen is off, disable GPS.
- disableGpsForPowerManager |=
- result.batterySaverEnabled && !mPowerManager.isInteractive();
- break;
- }
if (disableGpsForPowerManager != mDisableGpsForPowerManager) {
mDisableGpsForPowerManager = disableGpsForPowerManager;
updateEnabled();
@@ -1959,10 +1944,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ALARM_WAKEUP);
intentFilter.addAction(ALARM_TIMEOUT);
- intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
- intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
- intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
intentFilter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index e2f70e320cb8..eb4ab1ceac28 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -1937,7 +1937,8 @@ public class MediaSessionService extends SystemService implements Monitor {
// Context#getPackageName() for getting package name that matches with the PID/UID,
// but it doesn't tell which package has created the MediaController, so useless.
return hasMediaControlPermission(controllerPid, controllerUid)
- || hasEnabledNotificationListener(userId, controllerPackageName, uid);
+ || hasEnabledNotificationListener(
+ userId, controllerPackageName, controllerUid);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -2001,21 +2002,21 @@ public class MediaSessionService extends SystemService implements Monitor {
return resolvedUserId;
}
- private boolean hasEnabledNotificationListener(int resolvedUserId, String packageName,
- int uid) {
- // TODO: revisit this checking code
- // You may not access another user's content as an enabled listener.
- final int userId = UserHandle.getUserHandleForUid(resolvedUserId).getIdentifier();
- if (resolvedUserId != userId) {
+ private boolean hasEnabledNotificationListener(int callingUserId,
+ String controllerPackageName, int controllerUid) {
+ int controllerUserId = UserHandle.getUserHandleForUid(controllerUid).getIdentifier();
+ if (callingUserId != controllerUserId) {
+ // Enabled notification listener only works within the same user.
return false;
}
- if (mNotificationManager.hasEnabledNotificationListener(packageName,
- UserHandle.getUserHandleForUid(uid))) {
+
+ if (mNotificationManager.hasEnabledNotificationListener(controllerPackageName,
+ UserHandle.getUserHandleForUid(controllerUid))) {
return true;
}
if (DEBUG) {
- Log.d(TAG, packageName + " (uid=" + uid + ") doesn't have an enabled "
- + "notification listener");
+ Log.d(TAG, controllerPackageName + " (uid=" + controllerUid
+ + ") doesn't have an enabled notification listener");
}
return false;
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 3bd18f9a360f..006d78e4a648 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -70,9 +70,9 @@ public class NetworkPolicyLogger {
static final int NTWK_BLOCKED_POWER = 0;
static final int NTWK_ALLOWED_NON_METERED = 1;
- static final int NTWK_BLOCKED_BLACKLIST = 2;
- static final int NTWK_ALLOWED_WHITELIST = 3;
- static final int NTWK_ALLOWED_TMP_WHITELIST = 4;
+ static final int NTWK_BLOCKED_DENYLIST = 2;
+ static final int NTWK_ALLOWED_ALLOWLIST = 3;
+ static final int NTWK_ALLOWED_TMP_ALLOWLIST = 4;
static final int NTWK_BLOCKED_BG_RESTRICT = 5;
static final int NTWK_ALLOWED_DEFAULT = 6;
static final int NTWK_ALLOWED_SYSTEM = 7;
@@ -269,12 +269,12 @@ public class NetworkPolicyLogger {
return "blocked by power restrictions";
case NTWK_ALLOWED_NON_METERED:
return "allowed on unmetered network";
- case NTWK_BLOCKED_BLACKLIST:
- return "blacklisted on metered network";
- case NTWK_ALLOWED_WHITELIST:
- return "whitelisted on metered network";
- case NTWK_ALLOWED_TMP_WHITELIST:
- return "temporary whitelisted on metered network";
+ case NTWK_BLOCKED_DENYLIST:
+ return "denylisted on metered network";
+ case NTWK_ALLOWED_ALLOWLIST:
+ return "allowlisted on metered network";
+ case NTWK_ALLOWED_TMP_ALLOWLIST:
+ return "temporary allowlisted on metered network";
case NTWK_BLOCKED_BG_RESTRICT:
return "blocked when background is restricted";
case NTWK_ALLOWED_DEFAULT:
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index d6557f6410ec..295143e76235 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -101,13 +101,13 @@ import static com.android.internal.util.XmlUtils.writeIntAttribute;
import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.internal.util.XmlUtils.writeStringAttribute;
import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
+import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_ALLOWLIST;
import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_DEFAULT;
import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_NON_METERED;
import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_SYSTEM;
-import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_TMP_WHITELIST;
-import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_WHITELIST;
+import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_TMP_ALLOWLIST;
import static com.android.server.net.NetworkPolicyLogger.NTWK_BLOCKED_BG_RESTRICT;
-import static com.android.server.net.NetworkPolicyLogger.NTWK_BLOCKED_BLACKLIST;
+import static com.android.server.net.NetworkPolicyLogger.NTWK_BLOCKED_DENYLIST;
import static com.android.server.net.NetworkPolicyLogger.NTWK_BLOCKED_POWER;
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
@@ -507,7 +507,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* UIDs that have been initially white-listed by system to avoid restricted background.
*/
@GuardedBy("mUidRulesFirstLock")
- private final SparseBooleanArray mDefaultRestrictBackgroundWhitelistUids =
+ private final SparseBooleanArray mDefaultRestrictBackgroundAllowlistUids =
new SparseBooleanArray();
/**
@@ -515,7 +515,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* but later revoked by user.
*/
@GuardedBy("mUidRulesFirstLock")
- private final SparseBooleanArray mRestrictBackgroundWhitelistRevokedUids =
+ private final SparseBooleanArray mRestrictBackgroundAllowlistRevokedUids =
new SparseBooleanArray();
/** Set of ifaces that are metered. */
@@ -582,7 +582,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@GuardedBy("mUidRulesFirstLock")
private final SparseBooleanArray mInternetPermissionMap = new SparseBooleanArray();
- // TODO: keep whitelist of system-critical services that should never have
+ // TODO: keep allowlist of system-critical services that should never have
// rules enforced, such as system, phone, and radio UIDs.
// TODO: migrate notifications to SystemUI
@@ -668,26 +668,26 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
/**
- * Whitelists pre-defined apps for restrict background, but only if the user didn't already
- * revoke the whitelist.
+ * Allows pre-defined apps for restrict background, but only if the user didn't already
+ * revoked them.
*
- * @return whether any uid has been whitelisted.
+ * @return whether any uid has been allowlisted.
*/
@GuardedBy("mUidRulesFirstLock")
- boolean addDefaultRestrictBackgroundWhitelistUidsUL() {
+ boolean addDefaultRestrictBackgroundAllowlistUidsUL() {
final List<UserInfo> users = mUserManager.getUsers();
final int numberUsers = users.size();
boolean changed = false;
for (int i = 0; i < numberUsers; i++) {
final UserInfo user = users.get(i);
- changed = addDefaultRestrictBackgroundWhitelistUidsUL(user.id) || changed;
+ changed = addDefaultRestrictBackgroundAllowlistUidsUL(user.id) || changed;
}
return changed;
}
@GuardedBy("mUidRulesFirstLock")
- private boolean addDefaultRestrictBackgroundWhitelistUidsUL(int userId) {
+ private boolean addDefaultRestrictBackgroundAllowlistUidsUL(int userId) {
final SystemConfig sysConfig = SystemConfig.getInstance();
final PackageManager pm = mContext.getPackageManager();
final ArraySet<String> allowDataUsage = sysConfig.getAllowInDataUsageSave();
@@ -695,7 +695,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
for (int i = 0; i < allowDataUsage.size(); i++) {
final String pkg = allowDataUsage.valueAt(i);
if (LOGD)
- Slog.d(TAG, "checking restricted background whitelisting for package " + pkg
+ Slog.d(TAG, "checking restricted background allowlisting for package " + pkg
+ " and user " + userId);
final ApplicationInfo app;
try {
@@ -706,20 +706,20 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
continue;
}
if (!app.isPrivilegedApp()) {
- Slog.e(TAG, "addDefaultRestrictBackgroundWhitelistUidsUL(): "
+ Slog.e(TAG, "addDefaultRestrictBackgroundAllowlistUidsUL(): "
+ "skipping non-privileged app " + pkg);
continue;
}
final int uid = UserHandle.getUid(userId, app.uid);
- mDefaultRestrictBackgroundWhitelistUids.append(uid, true);
+ mDefaultRestrictBackgroundAllowlistUids.append(uid, true);
if (LOGD)
Slog.d(TAG, "Adding uid " + uid + " (user " + userId + ") to default restricted "
- + "background whitelist. Revoked status: "
- + mRestrictBackgroundWhitelistRevokedUids.get(uid));
- if (!mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
+ + "background allowlist. Revoked status: "
+ + mRestrictBackgroundAllowlistRevokedUids.get(uid));
+ if (!mRestrictBackgroundAllowlistRevokedUids.get(uid)) {
if (LOGD)
Slog.d(TAG, "adding default package " + pkg + " (uid " + uid + " for user "
- + userId + ") to restrict background whitelist");
+ + userId + ") to restrict background allowlist");
setUidPolicyUncheckedUL(uid, POLICY_ALLOW_METERED_BACKGROUND, false);
changed = true;
}
@@ -799,7 +799,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
});
- if (addDefaultRestrictBackgroundWhitelistUidsUL()) {
+ if (addDefaultRestrictBackgroundAllowlistUidsUL()) {
writePolicyAL();
}
@@ -1005,14 +1005,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
case ACTION_USER_ADDED:
synchronized (mUidRulesFirstLock) {
// Remove any persistable state for the given user; both cleaning up after a
- // USER_REMOVED, and one last sanity check during USER_ADDED
+ // USER_REMOVED, and one last check during USER_ADDED
removeUserStateUL(userId, true, false);
// Removing outside removeUserStateUL since that can also be called when
// user resets app preferences.
mMeteredRestrictedUids.remove(userId);
if (action == ACTION_USER_ADDED) {
- // Add apps that are whitelisted by default.
- addDefaultRestrictBackgroundWhitelistUidsUL(userId);
+ // Add apps that are allowlisted by default.
+ addDefaultRestrictBackgroundAllowlistUidsUL(userId);
}
// Update global restrict for that user
synchronized (mNetworkPoliciesSecondLock) {
@@ -2196,12 +2196,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
in.setInput(fis, StandardCharsets.UTF_8.name());
// Must save the <restrict-background> tags and convert them to <uid-policy> later,
- // to skip UIDs that were explicitly blacklisted.
- final SparseBooleanArray whitelistedRestrictBackground = new SparseBooleanArray();
+ // to skip UIDs that were explicitly denylisted.
+ final SparseBooleanArray allowlistedRestrictBackground = new SparseBooleanArray();
int type;
int version = VERSION_INIT;
- boolean insideWhitelist = false;
+ boolean insideAllowlist = false;
while ((type = in.next()) != END_DOCUMENT) {
final String tag = in.getName();
if (type == START_TAG) {
@@ -2340,28 +2340,28 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
}
} else if (TAG_WHITELIST.equals(tag)) {
- insideWhitelist = true;
- } else if (TAG_RESTRICT_BACKGROUND.equals(tag) && insideWhitelist) {
+ insideAllowlist = true;
+ } else if (TAG_RESTRICT_BACKGROUND.equals(tag) && insideAllowlist) {
final int uid = readIntAttribute(in, ATTR_UID);
- whitelistedRestrictBackground.append(uid, true);
- } else if (TAG_REVOKED_RESTRICT_BACKGROUND.equals(tag) && insideWhitelist) {
+ allowlistedRestrictBackground.append(uid, true);
+ } else if (TAG_REVOKED_RESTRICT_BACKGROUND.equals(tag) && insideAllowlist) {
final int uid = readIntAttribute(in, ATTR_UID);
- mRestrictBackgroundWhitelistRevokedUids.put(uid, true);
+ mRestrictBackgroundAllowlistRevokedUids.put(uid, true);
}
} else if (type == END_TAG) {
if (TAG_WHITELIST.equals(tag)) {
- insideWhitelist = false;
+ insideAllowlist = false;
}
}
}
- final int size = whitelistedRestrictBackground.size();
+ final int size = allowlistedRestrictBackground.size();
for (int i = 0; i < size; i++) {
- final int uid = whitelistedRestrictBackground.keyAt(i);
+ final int uid = allowlistedRestrictBackground.keyAt(i);
final int policy = mUidPolicy.get(uid, POLICY_NONE);
if ((policy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
- Slog.w(TAG, "ignoring restrict-background-whitelist for " + uid
+ Slog.w(TAG, "ignoring restrict-background-allowlist for " + uid
+ " because its policy is " + uidPoliciesToString(policy));
continue;
}
@@ -2533,13 +2533,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
out.endTag(null, TAG_POLICY_LIST);
- // write all whitelists
+ // write all allowlists
out.startTag(null, TAG_WHITELIST);
- // revoked restrict background whitelist
- int size = mRestrictBackgroundWhitelistRevokedUids.size();
+ // revoked restrict background allowlist
+ int size = mRestrictBackgroundAllowlistRevokedUids.size();
for (int i = 0; i < size; i++) {
- final int uid = mRestrictBackgroundWhitelistRevokedUids.keyAt(i);
+ final int uid = mRestrictBackgroundAllowlistRevokedUids.keyAt(i);
out.startTag(null, TAG_REVOKED_RESTRICT_BACKGROUND);
writeIntAttribute(out, ATTR_UID, uid);
out.endTag(null, TAG_REVOKED_RESTRICT_BACKGROUND);
@@ -2619,21 +2619,21 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
setUidPolicyUncheckedUL(uid, policy, false);
final boolean notifyApp;
- if (!isUidValidForWhitelistRulesUL(uid)) {
+ if (!isUidValidForAllowlistRulesUL(uid)) {
notifyApp = false;
} else {
- final boolean wasBlacklisted = oldPolicy == POLICY_REJECT_METERED_BACKGROUND;
- final boolean isBlacklisted = policy == POLICY_REJECT_METERED_BACKGROUND;
- final boolean wasWhitelisted = oldPolicy == POLICY_ALLOW_METERED_BACKGROUND;
- final boolean isWhitelisted = policy == POLICY_ALLOW_METERED_BACKGROUND;
- final boolean wasBlocked = wasBlacklisted || (mRestrictBackground && !wasWhitelisted);
- final boolean isBlocked = isBlacklisted || (mRestrictBackground && !isWhitelisted);
- if ((wasWhitelisted && (!isWhitelisted || isBlacklisted))
- && mDefaultRestrictBackgroundWhitelistUids.get(uid)
- && !mRestrictBackgroundWhitelistRevokedUids.get(uid)) {
+ final boolean wasDenylisted = oldPolicy == POLICY_REJECT_METERED_BACKGROUND;
+ final boolean isDenylisted = policy == POLICY_REJECT_METERED_BACKGROUND;
+ final boolean wasAllowlisted = oldPolicy == POLICY_ALLOW_METERED_BACKGROUND;
+ final boolean isAllowlisted = policy == POLICY_ALLOW_METERED_BACKGROUND;
+ final boolean wasBlocked = wasDenylisted || (mRestrictBackground && !wasAllowlisted);
+ final boolean isBlocked = isDenylisted || (mRestrictBackground && !isAllowlisted);
+ if ((wasAllowlisted && (!isAllowlisted || isDenylisted))
+ && mDefaultRestrictBackgroundAllowlistUids.get(uid)
+ && !mRestrictBackgroundAllowlistRevokedUids.get(uid)) {
if (LOGD)
- Slog.d(TAG, "Adding uid " + uid + " to revoked restrict background whitelist");
- mRestrictBackgroundWhitelistRevokedUids.append(uid, true);
+ Slog.d(TAG, "Adding uid " + uid + " to revoked restrict background allowlist");
+ mRestrictBackgroundAllowlistRevokedUids.append(uid, true);
}
notifyApp = wasBlocked != isBlocked;
}
@@ -2700,11 +2700,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mLogger.removingUserState(userId);
boolean changed = false;
- // Remove entries from revoked default restricted background UID whitelist
- for (int i = mRestrictBackgroundWhitelistRevokedUids.size() - 1; i >= 0; i--) {
- final int uid = mRestrictBackgroundWhitelistRevokedUids.keyAt(i);
+ // Remove entries from revoked default restricted background UID allowlist
+ for (int i = mRestrictBackgroundAllowlistRevokedUids.size() - 1; i >= 0; i--) {
+ final int uid = mRestrictBackgroundAllowlistRevokedUids.keyAt(i);
if (UserHandle.getUserId(uid) == userId) {
- mRestrictBackgroundWhitelistRevokedUids.removeAt(i);
+ mRestrictBackgroundAllowlistRevokedUids.removeAt(i);
changed = true;
}
}
@@ -2913,7 +2913,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
Slog.d(TAG, "setRestrictBackgroundUL(): " + restrictBackground + "; reason: " + reason);
final boolean oldRestrictBackground = mRestrictBackground;
mRestrictBackground = restrictBackground;
- // Must whitelist foreground apps before turning data saver mode on.
+ // Must allowlist foreground apps before turning data saver mode on.
// TODO: there is no need to iterate through all apps here, just those in the foreground,
// so it could call AM to get the UIDs of such apps, and iterate through them instead.
updateRulesForRestrictBackgroundUL();
@@ -2966,7 +2966,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
Binder.restoreCallingIdentity(token);
}
if (policy == POLICY_REJECT_METERED_BACKGROUND) {
- // App is blacklisted.
+ // App is denylisted.
return RESTRICT_BACKGROUND_STATUS_ENABLED;
}
if (!mRestrictBackground) {
@@ -3543,25 +3543,25 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
fout.decreaseIndent();
}
- size = mDefaultRestrictBackgroundWhitelistUids.size();
+ size = mDefaultRestrictBackgroundAllowlistUids.size();
if (size > 0) {
- fout.println("Default restrict background whitelist uids:");
+ fout.println("Default restrict background allowlist uids:");
fout.increaseIndent();
for (int i = 0; i < size; i++) {
fout.print("UID=");
- fout.print(mDefaultRestrictBackgroundWhitelistUids.keyAt(i));
+ fout.print(mDefaultRestrictBackgroundAllowlistUids.keyAt(i));
fout.println();
}
fout.decreaseIndent();
}
- size = mRestrictBackgroundWhitelistRevokedUids.size();
+ size = mRestrictBackgroundAllowlistRevokedUids.size();
if (size > 0) {
- fout.println("Default restrict background whitelist uids revoked by users:");
+ fout.println("Default restrict background allowlist uids revoked by users:");
fout.increaseIndent();
for (int i = 0; i < size; i++) {
fout.print("UID=");
- fout.print(mRestrictBackgroundWhitelistRevokedUids.keyAt(i));
+ fout.print(mRestrictBackgroundAllowlistRevokedUids.keyAt(i));
fout.println();
}
fout.decreaseIndent();
@@ -3882,7 +3882,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@GuardedBy("mUidRulesFirstLock")
void updateRuleForAppIdleUL(int uid) {
- if (!isUidValidForBlacklistRulesUL(uid)) return;
+ if (!isUidValidForDenylistRulesUL(uid)) return;
if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRuleForAppIdleUL: " + uid );
@@ -3915,13 +3915,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final SparseIntArray blockedUids = new SparseIntArray();
for (int i = 0; i < ruleCount; i++) {
final int uid = mUidFirewallStandbyRules.keyAt(i);
- if (!isUidValidForBlacklistRulesUL(uid)) {
+ if (!isUidValidForDenylistRulesUL(uid)) {
continue;
}
int oldRules = mUidRules.get(uid);
if (enableChain) {
// Chain wasn't enabled before and the other power-related
- // chains are whitelists, so we can clear the
+ // chains are allowlists, so we can clear the
// MASK_ALL_NETWORKS part of the rules and re-inform listeners if
// the effective rules result in blocking network access.
oldRules &= MASK_METERED_NETWORKS;
@@ -4079,10 +4079,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// TODO: the MEDIA / DRM restriction might not be needed anymore, in which case both
// methods below could be merged into a isUidValidForRules() method.
@GuardedBy("mUidRulesFirstLock")
- private boolean isUidValidForBlacklistRulesUL(int uid) {
+ private boolean isUidValidForDenylistRulesUL(int uid) {
// allow rules on specific system services, and any apps
if (uid == android.os.Process.MEDIA_UID || uid == android.os.Process.DRM_UID
- || isUidValidForWhitelistRulesUL(uid)) {
+ || isUidValidForAllowlistRulesUL(uid)) {
return true;
}
@@ -4090,7 +4090,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
@GuardedBy("mUidRulesFirstLock")
- private boolean isUidValidForWhitelistRulesUL(int uid) {
+ private boolean isUidValidForAllowlistRulesUL(int uid) {
return UserHandle.isApp(uid) && hasInternetPermissionUL(uid);
}
@@ -4235,23 +4235,23 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/**
* Applies network rules to bandwidth controllers based on process state and user-defined
- * restrictions (blacklist / whitelist).
+ * restrictions (allowlist / denylist).
*
* <p>
* {@code netd} defines 3 firewall chains that govern whether an app has access to metered
* networks:
* <ul>
- * <li>@{code bw_penalty_box}: UIDs added to this chain do not have access (blacklist).
- * <li>@{code bw_happy_box}: UIDs added to this chain have access (whitelist), unless they're
- * also blacklisted.
+ * <li>@{code bw_penalty_box}: UIDs added to this chain do not have access (denylist).
+ * <li>@{code bw_happy_box}: UIDs added to this chain have access (allowlist), unless they're
+ * also denylisted.
* <li>@{code bw_data_saver}: when enabled (through {@link #setRestrictBackground(boolean)}),
- * no UIDs other than those whitelisted will have access.
+ * no UIDs other than those allowlisted will have access.
* <ul>
*
* <p>The @{code bw_penalty_box} and @{code bw_happy_box} are primarily managed through the
- * {@link #setUidPolicy(int, int)} and {@link #addRestrictBackgroundWhitelistedUid(int)} /
- * {@link #removeRestrictBackgroundWhitelistedUid(int)} methods (for blacklist and whitelist
- * respectively): these methods set the proper internal state (blacklist / whitelist), then call
+ * {@link #setUidPolicy(int, int)} and {@link #addRestrictBackgroundAllowlistedUid(int)} /
+ * {@link #removeRestrictBackgroundDenylistedUid(int)} methods (for denylist and allowlist
+ * respectively): these methods set the proper internal state (denylist / allowlist), then call
* this ({@link #updateRulesForDataUsageRestrictionsUL(int)}) to propagate the rules to
* {@link INetworkManagementService}, but this method should also be called in events (like
* Data Saver Mode flips or UID state changes) that might affect the foreground app, since the
@@ -4260,7 +4260,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* <ul>
* <li>When Data Saver mode is on, the foreground app should be temporarily added to
* {@code bw_happy_box} before the @{code bw_data_saver} chain is enabled.
- * <li>If the foreground app is blacklisted by the user, it should be temporarily removed from
+ * <li>If the foreground app is denylisted by the user, it should be temporarily removed from
* {@code bw_penalty_box}.
* <li>When the app leaves foreground state, the temporary changes above should be reverted.
* </ul>
@@ -4285,7 +4285,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
private void updateRulesForDataUsageRestrictionsULInner(int uid) {
- if (!isUidValidForWhitelistRulesUL(uid)) {
+ if (!isUidValidForAllowlistRulesUL(uid)) {
if (LOGD) Slog.d(TAG, "no need to update restrict data rules for uid " + uid);
return;
}
@@ -4295,8 +4295,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final boolean isForeground = isUidForegroundOnRestrictBackgroundUL(uid);
final boolean isRestrictedByAdmin = isRestrictedByAdminUL(uid);
- final boolean isBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
- final boolean isWhitelisted = (uidPolicy & POLICY_ALLOW_METERED_BACKGROUND) != 0;
+ final boolean isDenylisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
+ final boolean isAllowlisted = (uidPolicy & POLICY_ALLOW_METERED_BACKGROUND) != 0;
final int oldRule = oldUidRules & MASK_METERED_NETWORKS;
int newRule = RULE_NONE;
@@ -4304,15 +4304,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (isRestrictedByAdmin) {
newRule = RULE_REJECT_METERED;
} else if (isForeground) {
- if (isBlacklisted || (mRestrictBackground && !isWhitelisted)) {
+ if (isDenylisted || (mRestrictBackground && !isAllowlisted)) {
newRule = RULE_TEMPORARY_ALLOW_METERED;
- } else if (isWhitelisted) {
+ } else if (isAllowlisted) {
newRule = RULE_ALLOW_METERED;
}
} else {
- if (isBlacklisted) {
+ if (isDenylisted) {
newRule = RULE_REJECT_METERED;
- } else if (mRestrictBackground && isWhitelisted) {
+ } else if (mRestrictBackground && isAllowlisted) {
newRule = RULE_ALLOW_METERED;
}
}
@@ -4321,8 +4321,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (LOGV) {
Log.v(TAG, "updateRuleForRestrictBackgroundUL(" + uid + ")"
+ ": isForeground=" +isForeground
- + ", isBlacklisted=" + isBlacklisted
- + ", isWhitelisted=" + isWhitelisted
+ + ", isDenylisted=" + isDenylisted
+ + ", isAllowlisted=" + isAllowlisted
+ ", isRestrictedByAdmin=" + isRestrictedByAdmin
+ ", oldRule=" + uidRulesToString(oldRule)
+ ", newRule=" + uidRulesToString(newRule)
@@ -4339,49 +4339,49 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// Second step: apply bw changes based on change of state.
if (newRule != oldRule) {
if (hasRule(newRule, RULE_TEMPORARY_ALLOW_METERED)) {
- // Temporarily whitelist foreground app, removing from blacklist if necessary
+ // Temporarily allowlist foreground app, removing from denylist if necessary
// (since bw_penalty_box prevails over bw_happy_box).
- setMeteredNetworkWhitelist(uid, true);
+ setMeteredNetworkAllowlist(uid, true);
// TODO: if statement below is used to avoid an unnecessary call to netd / iptables,
// but ideally it should be just:
- // setMeteredNetworkBlacklist(uid, isBlacklisted);
- if (isBlacklisted) {
- setMeteredNetworkBlacklist(uid, false);
+ // setMeteredNetworkDenylist(uid, isDenylisted);
+ if (isDenylisted) {
+ setMeteredNetworkDenylist(uid, false);
}
} else if (hasRule(oldRule, RULE_TEMPORARY_ALLOW_METERED)) {
- // Remove temporary whitelist from app that is not on foreground anymore.
+ // Remove temporary allowlist from app that is not on foreground anymore.
// TODO: if statements below are used to avoid unnecessary calls to netd / iptables,
// but ideally they should be just:
- // setMeteredNetworkWhitelist(uid, isWhitelisted);
- // setMeteredNetworkBlacklist(uid, isBlacklisted);
- if (!isWhitelisted) {
- setMeteredNetworkWhitelist(uid, false);
+ // setMeteredNetworkAllowlist(uid, isAllowlisted);
+ // setMeteredNetworkDenylist(uid, isDenylisted);
+ if (!isAllowlisted) {
+ setMeteredNetworkAllowlist(uid, false);
}
- if (isBlacklisted || isRestrictedByAdmin) {
- setMeteredNetworkBlacklist(uid, true);
+ if (isDenylisted || isRestrictedByAdmin) {
+ setMeteredNetworkDenylist(uid, true);
}
} else if (hasRule(newRule, RULE_REJECT_METERED)
|| hasRule(oldRule, RULE_REJECT_METERED)) {
- // Flip state because app was explicitly added or removed to blacklist.
- setMeteredNetworkBlacklist(uid, (isBlacklisted || isRestrictedByAdmin));
- if (hasRule(oldRule, RULE_REJECT_METERED) && isWhitelisted) {
- // Since blacklist prevails over whitelist, we need to handle the special case
- // where app is whitelisted and blacklisted at the same time (although such
- // scenario should be blocked by the UI), then blacklist is removed.
- setMeteredNetworkWhitelist(uid, isWhitelisted);
+ // Flip state because app was explicitly added or removed to denylist.
+ setMeteredNetworkDenylist(uid, (isDenylisted || isRestrictedByAdmin));
+ if (hasRule(oldRule, RULE_REJECT_METERED) && isAllowlisted) {
+ // Since dneylist prevails over allowlist, we need to handle the special case
+ // where app is allowlisted and denylisted at the same time (although such
+ // scenario should be blocked by the UI), then denylist is removed.
+ setMeteredNetworkAllowlist(uid, isAllowlisted);
}
} else if (hasRule(newRule, RULE_ALLOW_METERED)
|| hasRule(oldRule, RULE_ALLOW_METERED)) {
- // Flip state because app was explicitly added or removed to whitelist.
- setMeteredNetworkWhitelist(uid, isWhitelisted);
+ // Flip state because app was explicitly added or removed to allowlist.
+ setMeteredNetworkAllowlist(uid, isAllowlisted);
} else {
// All scenarios should have been covered above.
Log.wtf(TAG, "Unexpected change of metered UID state for " + uid
+ ": foreground=" + isForeground
- + ", whitelisted=" + isWhitelisted
- + ", blacklisted=" + isBlacklisted
+ + ", allowlisted=" + isAllowlisted
+ + ", denylisted=" + isDenylisted
+ ", isRestrictedByAdmin=" + isRestrictedByAdmin
+ ", newRule=" + uidRulesToString(newUidRules)
+ ", oldRule=" + uidRulesToString(oldUidRules));
@@ -4397,7 +4397,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* listeners in case of change.
* <p>
* There are 3 power-related rules that affects whether an app has background access on
- * non-metered networks, and when the condition applies and the UID is not whitelisted for power
+ * non-metered networks, and when the condition applies and the UID is not allowlisted for power
* restriction, it's added to the equivalent firewall chain:
* <ul>
* <li>App is idle: {@code fw_standby} firewall chain.
@@ -4406,7 +4406,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* </ul>
* <p>
* This method updates the power-related part of the {@link #mUidRules} for a given uid based on
- * these modes, the UID process state (foreground or not), and the UIDwhitelist state.
+ * these modes, the UID process state (foreground or not), and the UID allowlist state.
* <p>
* <strong>NOTE: </strong>This method does not update the firewall rules on {@code netd}.
*/
@@ -4450,7 +4450,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@GuardedBy("mUidRulesFirstLock")
private int updateRulesForPowerRestrictionsULInner(int uid, int oldUidRules,
boolean isUidIdle) {
- if (!isUidValidForBlacklistRulesUL(uid)) {
+ if (!isUidValidForDenylistRulesUL(uid)) {
if (LOGD) Slog.d(TAG, "no need to update restrict power rules for uid " + uid);
return RULE_NONE;
}
@@ -4859,23 +4859,23 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
- private void setMeteredNetworkBlacklist(int uid, boolean enable) {
- if (LOGV) Slog.v(TAG, "setMeteredNetworkBlacklist " + uid + ": " + enable);
+ private void setMeteredNetworkDenylist(int uid, boolean enable) {
+ if (LOGV) Slog.v(TAG, "setMeteredNetworkDenylist " + uid + ": " + enable);
try {
- mNetworkManager.setUidMeteredNetworkBlacklist(uid, enable);
+ mNetworkManager.setUidMeteredNetworkDenylist(uid, enable);
} catch (IllegalStateException e) {
- Log.wtf(TAG, "problem setting blacklist (" + enable + ") rules for " + uid, e);
+ Log.wtf(TAG, "problem setting denylist (" + enable + ") rules for " + uid, e);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
}
- private void setMeteredNetworkWhitelist(int uid, boolean enable) {
- if (LOGV) Slog.v(TAG, "setMeteredNetworkWhitelist " + uid + ": " + enable);
+ private void setMeteredNetworkAllowlist(int uid, boolean enable) {
+ if (LOGV) Slog.v(TAG, "setMeteredNetworkAllowlist " + uid + ": " + enable);
try {
- mNetworkManager.setUidMeteredNetworkWhitelist(uid, enable);
+ mNetworkManager.setUidMeteredNetworkAllowlist(uid, enable);
} catch (IllegalStateException e) {
- Log.wtf(TAG, "problem setting whitelist (" + enable + ") rules for " + uid, e);
+ Log.wtf(TAG, "problem setting allowlist (" + enable + ") rules for " + uid, e);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
@@ -4936,7 +4936,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
/**
- * Add or remove a uid to the firewall blacklist for all network ifaces.
+ * Add or remove a uid to the firewall denylist for all network ifaces.
*/
private void setUidFirewallRule(int chain, int uid, int rule) {
if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
@@ -4966,7 +4966,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
/**
- * Add or remove a uid to the firewall blacklist for all network ifaces.
+ * Add or remove a uid to the firewall denylist for all network ifaces.
*/
@GuardedBy("mUidRulesFirstLock")
private void enableFirewallChainUL(int chain, boolean enable) {
@@ -4995,8 +4995,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
mNetworkManager
.setFirewallUidRule(FIREWALL_CHAIN_POWERSAVE, uid, FIREWALL_RULE_DEFAULT);
- mNetworkManager.setUidMeteredNetworkWhitelist(uid, false);
- mNetworkManager.setUidMeteredNetworkBlacklist(uid, false);
+ mNetworkManager.setUidMeteredNetworkAllowlist(uid, false);
+ mNetworkManager.setUidMeteredNetworkDenylist(uid, false);
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem resetting firewall uid rules for " + uid, e);
} catch (RemoteException e) {
@@ -5189,13 +5189,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
reason = NTWK_ALLOWED_NON_METERED;
}
else if (hasRule(uidRules, RULE_REJECT_METERED)) {
- reason = NTWK_BLOCKED_BLACKLIST;
+ reason = NTWK_BLOCKED_DENYLIST;
}
else if (hasRule(uidRules, RULE_ALLOW_METERED)) {
- reason = NTWK_ALLOWED_WHITELIST;
+ reason = NTWK_ALLOWED_ALLOWLIST;
}
else if (hasRule(uidRules, RULE_TEMPORARY_ALLOW_METERED)) {
- reason = NTWK_ALLOWED_TMP_WHITELIST;
+ reason = NTWK_ALLOWED_TMP_ALLOWLIST;
}
else if (isBackgroundRestricted) {
reason = NTWK_BLOCKED_BG_RESTRICT;
@@ -5208,13 +5208,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
switch(reason) {
case NTWK_ALLOWED_DEFAULT:
case NTWK_ALLOWED_NON_METERED:
- case NTWK_ALLOWED_TMP_WHITELIST:
- case NTWK_ALLOWED_WHITELIST:
+ case NTWK_ALLOWED_TMP_ALLOWLIST:
+ case NTWK_ALLOWED_ALLOWLIST:
case NTWK_ALLOWED_SYSTEM:
blocked = false;
break;
case NTWK_BLOCKED_POWER:
- case NTWK_BLOCKED_BLACKLIST:
+ case NTWK_BLOCKED_DENYLIST:
case NTWK_BLOCKED_BG_RESTRICT:
blocked = true;
break;
@@ -5234,7 +5234,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
public void resetUserState(int userId) {
synchronized (mUidRulesFirstLock) {
boolean changed = removeUserStateUL(userId, false, true);
- changed = addDefaultRestrictBackgroundWhitelistUidsUL(userId) || changed;
+ changed = addDefaultRestrictBackgroundAllowlistUidsUL(userId) || changed;
if (changed) {
synchronized (mNetworkPoliciesSecondLock) {
writePolicyAL();
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 840645edcb82..8af74631fb2e 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -613,6 +613,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
throw new IllegalArgumentException(
"APEX files can only be installed as part of a staged session.");
}
+ if (params.isMultiPackage) {
+ throw new IllegalArgumentException("A multi-session can't be set as APEX.");
+ }
}
if (params.isStaged && !isCalledBySystemOrShell(callingUid)) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index ff9edd511e84..2807a1e4c081 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1637,7 +1637,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
* If session should be sealed, then it's sealed to prevent further modification.
* If the session can't be sealed then it's destroyed.
*
- * Additionally for staged APEX sessions read+validate the package and populate req'd fields.
+ * Additionally for staged APEX/APK sessions read+validate the package and populate req'd
+ * fields.
*
* <p> This is meant to be called after all of the sessions are loaded and added to
* PackageInstallerService
@@ -1670,6 +1671,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
// APEX installations rely on certain fields to be populated after reboot.
// E.g. mPackageName.
validateApexInstallLocked();
+ } else {
+ // Populate mPackageName for this APK session which is required by the staging
+ // manager to check duplicate apk-in-apex.
+ PackageInstallerSession parent = allSessions.get(mParentSessionId);
+ if (parent != null && parent.isStagedSessionReady()) {
+ validateApkInstallLocked();
+ }
}
} catch (PackageManagerException e) {
Slog.e(TAG, "Package not valid", e);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a874f612e106..572892bd6ff5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -103,7 +103,6 @@ import static android.os.incremental.IncrementalManager.isIncrementalPath;
import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
-import static android.permission.PermissionManager.KILL_APP_REASON_GIDS_CHANGED;
import static com.android.internal.annotations.VisibleForTesting.Visibility;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
@@ -365,7 +364,6 @@ import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.pm.permission.BasePermission;
import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
-import com.android.server.pm.permission.PermissionsState;
import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.rollback.RollbackManagerInternal;
import com.android.server.security.VerityUtils;
@@ -1807,7 +1805,7 @@ public class PackageManagerService extends IPackageManager.Stub
synchronized (mLock) {
removeMessages(WRITE_SETTINGS);
removeMessages(WRITE_PACKAGE_RESTRICTIONS);
- mSettings.writeLPr();
+ writeSettingsLPrTEMP();
mDirtyUsers.clear();
}
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
@@ -1827,6 +1825,7 @@ public class PackageManagerService extends IPackageManager.Stub
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
synchronized (mLock) {
removeMessages(WRITE_PACKAGE_LIST);
+ mPermissionManager.writePermissionsStateToPackageSettingsTEMP();
mSettings.writePackageListLPr(msg.arg1);
}
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
@@ -2232,7 +2231,7 @@ public class PackageManagerService extends IPackageManager.Stub
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
installerPackageName, null /*finishedReceiver*/,
- updateUserIds, instantUserIds, null /* broadcastWhitelist */);
+ updateUserIds, instantUserIds, null /* broadcastAllowList */);
}
// if the required verifier is defined, but, is not the installer of record
// for the package, it gets notified
@@ -2242,7 +2241,7 @@ public class PackageManagerService extends IPackageManager.Stub
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
mRequiredVerifierPackage, null /*finishedReceiver*/,
- updateUserIds, instantUserIds, null /* broadcastWhitelist */);
+ updateUserIds, instantUserIds, null /* broadcastAllowList */);
}
// If package installer is defined, notify package installer about new
// app installed
@@ -2250,7 +2249,7 @@ public class PackageManagerService extends IPackageManager.Stub
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND /*flags*/,
mRequiredInstallerPackage, null /*finishedReceiver*/,
- firstUserIds, instantUserIds, null /* broadcastWhitelist */);
+ firstUserIds, instantUserIds, null /* broadcastAllowList */);
}
// Send replaced for users that don't see the package for the first time
@@ -2263,19 +2262,19 @@ public class PackageManagerService extends IPackageManager.Stub
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
extras, 0 /*flags*/,
installerPackageName, null /*finishedReceiver*/,
- updateUserIds, instantUserIds, null /*broadcastWhitelist*/);
+ updateUserIds, instantUserIds, null /*broadcastAllowList*/);
}
if (notifyVerifier) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
extras, 0 /*flags*/,
mRequiredVerifierPackage, null /*finishedReceiver*/,
- updateUserIds, instantUserIds, null /*broadcastWhitelist*/);
+ updateUserIds, instantUserIds, null /*broadcastAllowList*/);
}
sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
null /*package*/, null /*extras*/, 0 /*flags*/,
packageName /*targetPackage*/,
null /*finishedReceiver*/, updateUserIds, instantUserIds,
- null /*broadcastWhitelist*/);
+ null /*broadcastAllowList*/);
} else if (launchedForRestore && !res.pkg.isSystem()) {
// First-install and we did a restore, so we're responsible for the
// first-launch broadcast.
@@ -2507,7 +2506,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
mSettings.onVolumeForgotten(fsUuid);
- mSettings.writeLPr();
+ writeSettingsLPrTEMP();
}
}
};
@@ -3427,6 +3426,7 @@ public class PackageManagerService extends IPackageManager.Stub
+ ((SystemClock.uptimeMillis()-startTime)/1000f)
+ " seconds");
+ mPermissionManager.readPermissionsStateFromPackageSettingsTEMP();
// If the platform SDK has changed since the last time we booted,
// we need to re-grant app permission to catch any new ones that
// appear. This is really a hack, and means that apps can in some
@@ -3544,7 +3544,7 @@ public class PackageManagerService extends IPackageManager.Stub
// can downgrade to reader
t.traceBegin("write settings");
- mSettings.writeLPr();
+ writeSettingsLPrTEMP();
t.traceEnd();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
@@ -3748,7 +3748,7 @@ public class PackageManagerService extends IPackageManager.Stub
Slog.e(TAG, "updateAllSharedLibrariesLPw failed: ", e);
}
mPermissionManager.updatePermissions(pkg.getPackageName(), pkg);
- mSettings.writeLPr();
+ writeSettingsLPrTEMP();
}
} catch (PackageManagerException e) {
// Whoops! Something went very wrong; roll back to the stub and disable the package
@@ -3759,9 +3759,8 @@ public class PackageManagerService extends IPackageManager.Stub
// If we don't, installing the system package fails during scan
enableSystemPackageLPw(stubPkg);
}
- installPackageFromSystemLIF(stubPkg.getCodePath(),
- null /*allUserHandles*/, null /*origUserHandles*/,
- null /*origPermissionsState*/, true /*writeSettings*/);
+ installPackageFromSystemLIF(stubPkg.getCodePath(), null /*allUserHandles*/,
+ null /*origUserHandles*/, true /*writeSettings*/);
} catch (PackageManagerException pme) {
// Serious WTF; we have to be able to install the stub
Slog.wtf(TAG, "Failed to restore system package:" + stubPkg.getPackageName(),
@@ -3775,7 +3774,7 @@ public class PackageManagerService extends IPackageManager.Stub
stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED,
UserHandle.USER_SYSTEM, "android");
}
- mSettings.writeLPr();
+ writeSettingsLPrTEMP();
}
}
return false;
@@ -14627,7 +14626,7 @@ public class PackageManagerService extends IPackageManager.Stub
private void sendFirstLaunchBroadcast(String pkgName, String installerPkg,
int[] userIds, int[] instantUserIds) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_FIRST_LAUNCH, pkgName, null, 0,
- installerPkg, null, userIds, instantUserIds, null /* broadcastWhitelist */);
+ installerPkg, null, userIds, instantUserIds, null /* broadcastAllowList */);
}
private abstract class HandlerParams {
@@ -16263,7 +16262,7 @@ public class PackageManagerService extends IPackageManager.Stub
res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
//to update install status
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "writeSettings");
- mSettings.writeLPr();
+ writeSettingsLPrTEMP();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
@@ -18730,14 +18729,14 @@ public class PackageManagerService extends IPackageManager.Stub
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, removedPackage,
extras, 0, null /*targetPackage*/, null, null, null, broadcastAllowList);
packageSender.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, 0,
- removedPackage, null, null, null, null /* broadcastWhitelist */);
+ removedPackage, null, null, null, null /* broadcastAllowList */);
if (installerPackageName != null) {
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
removedPackage, extras, 0 /*flags*/,
- installerPackageName, null, null, null, null /* broadcastWhitelist */);
+ installerPackageName, null, null, null, null /* broadcastAllowList */);
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
removedPackage, extras, 0 /*flags*/,
- installerPackageName, null, null, null, null /* broadcastWhitelist */);
+ installerPackageName, null, null, null, null /* broadcastAllowList */);
}
}
@@ -18863,29 +18862,11 @@ public class PackageManagerService extends IPackageManager.Stub
if (outInfo != null) {
outInfo.removedAppId = removedAppId;
}
- mPermissionManager.updatePermissions(deletedPs.name, null);
- if (deletedPs.sharedUser != null) {
- // Remove permissions associated with package. Since runtime
- // permissions are per user we have to kill the removed package
- // or packages running under the shared user of the removed
- // package if revoking the permissions requested only by the removed
- // package is successful and this causes a change in gids.
- boolean shouldKill = false;
- for (int userId : UserManagerService.getInstance().getUserIds()) {
- final int userIdToKill = mSettings.updateSharedUserPermsLPw(deletedPs,
- userId);
- shouldKill |= userIdToKill == UserHandle.USER_ALL
- || userIdToKill >= UserHandle.USER_SYSTEM;
- }
- // If gids changed, kill all affected packages.
- if (shouldKill) {
- mHandler.post(() -> {
- // This has to happen with no lock held.
- killApplication(deletedPs.name, deletedPs.appId,
- KILL_APP_REASON_GIDS_CHANGED);
- });
- }
+ if ((deletedPs.sharedUser == null || deletedPs.sharedUser.packages.size() == 0)
+ && !isUpdatedSystemApp(deletedPs)) {
+ mPermissionManager.removePermissionsStateTEMP(removedAppId);
}
+ mPermissionManager.updatePermissions(deletedPs.name, null);
clearPackagePreferredActivitiesLPw(
deletedPs.name, changedUsers, UserHandle.USER_ALL);
}
@@ -18919,7 +18900,7 @@ public class PackageManagerService extends IPackageManager.Stub
// can downgrade to reader
if (writeSettings) {
// Save settings now
- mSettings.writeLPr();
+ writeSettingsLPrTEMP();
}
if (installedStateChanged) {
mSettings.writeKernelMappingLPr(deletedPs);
@@ -19006,8 +18987,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs);
try {
installPackageFromSystemLIF(disabledPs.getCodePathString(), allUserHandles,
- outInfo == null ? null : outInfo.origUsers, deletedPs.getPermissionsState(),
- writeSettings);
+ outInfo == null ? null : outInfo.origUsers, writeSettings);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to restore system package:" + deletedPkg.getPackageName() + ": "
+ e.getMessage());
@@ -19038,9 +19018,8 @@ public class PackageManagerService extends IPackageManager.Stub
* Installs a package that's already on the system partition.
*/
private AndroidPackage installPackageFromSystemLIF(@NonNull String codePathString,
- @Nullable int[] allUserHandles, @Nullable int[] origUserHandles,
- @Nullable PermissionsState origPermissionState, boolean writeSettings)
- throws PackageManagerException {
+ @Nullable int[] allUserHandles, @Nullable int[] origUserHandles, boolean writeSettings)
+ throws PackageManagerException {
final File codePath = new File(codePathString);
@ParseFlags int parseFlags =
mDefParseFlags
@@ -19077,12 +19056,8 @@ public class PackageManagerService extends IPackageManager.Stub
synchronized (mLock) {
PackageSetting ps = mSettings.mPackages.get(pkg.getPackageName());
- // Propagate the permissions state as we do not want to drop on the floor
- // runtime permissions. The update permissions method below will take
- // care of removing obsolete permissions and grant install permissions.
- if (origPermissionState != null) {
- ps.getPermissionsState().copyFrom(origPermissionState);
- }
+ // The update permissions method below will take care of removing obsolete permissions
+ // and granting install permissions.
mPermissionManager.updatePermissions(pkg.getPackageName(), pkg);
final boolean applyUserRestrictions
@@ -19116,7 +19091,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
// can downgrade to reader here
if (writeSettings) {
- mSettings.writeLPr();
+ writeSettingsLPrTEMP();
}
}
return pkg;
@@ -19190,7 +19165,7 @@ public class PackageManagerService extends IPackageManager.Stub
} else {
ps.pkgPrivateFlags &= ~ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER;
}
- mSettings.writeLPr();
+ writeSettingsLPrTEMP();
}
return true;
}
@@ -20382,7 +20357,7 @@ public class PackageManagerService extends IPackageManager.Stub
(parser1, userId1) -> {
synchronized (mLock) {
mSettings.readAllDomainVerificationsLPr(parser1, userId1);
- mSettings.writeLPr();
+ writeSettingsLPrTEMP();
}
});
} catch (Exception e) {
@@ -21733,6 +21708,8 @@ public class PackageManagerService extends IPackageManager.Stub
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
+ mPermissionManager.writePermissionsStateToPackageSettingsTEMP();
+
DumpState dumpState = new DumpState();
boolean fullPreferred = false;
boolean checkin = false;
@@ -21928,7 +21905,7 @@ public class PackageManagerService extends IPackageManager.Stub
dumpState.setDump(DumpState.DUMP_SERVICE_PERMISSIONS);
} else if ("write".equals(cmd)) {
synchronized (mLock) {
- mSettings.writeLPr();
+ writeSettingsLPrTEMP();
pw.println("Settings written.");
return;
}
@@ -22646,7 +22623,7 @@ public class PackageManagerService extends IPackageManager.Stub
// Yay, everything is now upgraded
ver.forceCurrent();
- mSettings.writeLPr();
+ writeSettingsLPrTEMP();
}
for (PackageFreezer freezer : freezers) {
@@ -22696,7 +22673,7 @@ public class PackageManagerService extends IPackageManager.Stub
AttributeCache.instance().removePackage(ps.name);
}
- mSettings.writeLPr();
+ writeSettingsLPrTEMP();
}
}
@@ -23575,6 +23552,8 @@ public class PackageManagerService extends IPackageManager.Stub
synchronized (mLock) {
mDirtyUsers.remove(userId);
mUserNeedsBadging.delete(userId);
+ mPermissionManager.onUserRemoved(userId);
+ mPermissionManager.writePermissionsStateToPackageSettingsTEMP();
mSettings.removeUserLPw(userId);
mPendingBroadcasts.remove(userId);
mInstantAppRegistry.onUserRemovedLPw(userId);
@@ -25131,7 +25110,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (async) {
scheduleWriteSettingsLocked();
} else {
- mSettings.writeLPr();
+ writeSettingsLPrTEMP();
}
}
}
@@ -25178,7 +25157,7 @@ public class PackageManagerService extends IPackageManager.Stub
return;
}
mSettings.mReadExternalStorageEnforced = enforced ? Boolean.TRUE : Boolean.FALSE;
- mSettings.writeLPr();
+ writeSettingsLPrTEMP();
}
}
@@ -25692,6 +25671,17 @@ public class PackageManagerService extends IPackageManager.Stub
public List<String> getMimeGroup(String packageName, String mimeGroup) {
return mSettings.mPackages.get(packageName).getMimeGroup(mimeGroup);
}
+
+ /**
+ * Temporary method that wraps mSettings.writeLPr() and calls
+ * mPermissionManager.writePermissionsStateToPackageSettingsTEMP() beforehand.
+ *
+ * TODO(zhanghai): This should be removed once we finish migration of permission storage.
+ */
+ private void writeSettingsLPrTEMP() {
+ mPermissionManager.writePermissionsStateToPackageSettingsTEMP();
+ mSettings.writeLPr();
+ }
}
interface PackageSender {
@@ -25700,9 +25690,9 @@ interface PackageSender {
* @param instantUserIds User IDs where the action occurred on an instant application
*/
void sendPackageBroadcast(final String action, final String pkg,
- final Bundle extras, final int flags, final String targetPkg,
- final IIntentReceiver finishedReceiver, final int[] userIds, int[] instantUserIds,
- @Nullable SparseArray<int[]> broadcastWhitelist);
+ final Bundle extras, final int flags, final String targetPkg,
+ final IIntentReceiver finishedReceiver, final int[] userIds, int[] instantUserIds,
+ @Nullable SparseArray<int[]> broadcastAllowList);
void sendPackageAddedForNewUsers(String packageName, boolean sendBootCompleted,
boolean includeStopped, int appId, int[] userIds, int[] instantUserIds,
int dataLoaderType);
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index de0e4b53adab..491b4fc515ce 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -34,7 +34,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfoLite;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.PackageParserException;
import android.content.pm.ResolveInfo;
@@ -68,7 +67,6 @@ import com.android.server.EventLogTags;
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.PackageDexUsage;
import com.android.server.pm.parsing.pkg.AndroidPackage;
-import com.android.server.pm.permission.PermissionsState;
import dalvik.system.VMRuntime;
@@ -968,20 +966,6 @@ public class PackageManagerServiceUtils {
}
/**
- * Returns the {@link PermissionsState} for the given package. If the {@link PermissionsState}
- * could not be found, {@code null} will be returned.
- */
- public static PermissionsState getPermissionsState(
- PackageManagerInternal packageManagerInternal, AndroidPackage pkg) {
- final PackageSetting packageSetting = packageManagerInternal.getPackageSetting(
- pkg.getPackageName());
- if (packageSetting == null) {
- return null;
- }
- return packageSetting.getPermissionsState();
- }
-
- /**
* Recursively create target directory
*/
public static void makeDirRecursive(File targetDir, int mode) throws ErrnoException {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 3e3e3c590491..8ceed139a5e5 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -954,93 +954,6 @@ public final class Settings {
}
}
- /*
- * Update the shared user setting when a package with a shared user id is removed. The gids
- * associated with each permission of the deleted package are removed from the shared user'
- * gid list only if its not in use by other permissions of packages in the shared user setting.
- *
- * @return the affected user id
- */
- @UserIdInt
- int updateSharedUserPermsLPw(PackageSetting deletedPs, int userId) {
- if ((deletedPs == null) || (deletedPs.pkg == null)) {
- Slog.i(PackageManagerService.TAG,
- "Trying to update info for null package. Just ignoring");
- return UserHandle.USER_NULL;
- }
-
- // No sharedUserId
- if (deletedPs.sharedUser == null) {
- return UserHandle.USER_NULL;
- }
-
- SharedUserSetting sus = deletedPs.sharedUser;
-
- int affectedUserId = UserHandle.USER_NULL;
- // Update permissions
- for (String eachPerm : deletedPs.pkg.getRequestedPermissions()) {
- BasePermission bp = mPermissions.getPermission(eachPerm);
- if (bp == null) {
- continue;
- }
-
- // Check if another package in the shared user needs the permission.
- boolean used = false;
- for (PackageSetting pkg : sus.packages) {
- if (pkg.pkg != null
- && !pkg.pkg.getPackageName().equals(deletedPs.pkg.getPackageName())
- && pkg.pkg.getRequestedPermissions().contains(eachPerm)) {
- used = true;
- break;
- }
- }
- if (used) {
- continue;
- }
-
- PermissionsState permissionsState = sus.getPermissionsState();
- PackageSetting disabledPs = getDisabledSystemPkgLPr(deletedPs.pkg.getPackageName());
-
- // If the package is shadowing is a disabled system package,
- // do not drop permissions that the shadowed package requests.
- if (disabledPs != null) {
- boolean reqByDisabledSysPkg = false;
- for (String permission : disabledPs.pkg.getRequestedPermissions()) {
- if (permission.equals(eachPerm)) {
- reqByDisabledSysPkg = true;
- break;
- }
- }
- if (reqByDisabledSysPkg) {
- continue;
- }
- }
-
- // Try to revoke as an install permission which is for all users.
- // The package is gone - no need to keep flags for applying policy.
- permissionsState.updatePermissionFlags(bp, userId,
- PackageManager.MASK_PERMISSION_FLAGS_ALL, 0);
-
- if (permissionsState.revokeInstallPermission(bp) ==
- PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) {
- affectedUserId = UserHandle.USER_ALL;
- }
-
- // Try to revoke as an install permission which is per user.
- if (permissionsState.revokeRuntimePermission(bp, userId) ==
- PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) {
- if (affectedUserId == UserHandle.USER_NULL) {
- affectedUserId = userId;
- } else if (affectedUserId != userId) {
- // Multiple users affected.
- affectedUserId = UserHandle.USER_ALL;
- }
- }
- }
-
- return affectedUserId;
- }
-
int removePackageLPw(String name) {
final PackageSetting p = mPackages.get(name);
if (p != null) {
@@ -4647,6 +4560,9 @@ public final class Settings {
pw.print(prefix); pw.print(" resourcePath="); pw.println(ps.getCodePathString());
pw.print(prefix); pw.print(" legacyNativeLibraryDir=");
pw.println(ps.legacyNativeLibraryPathString);
+ pw.print(prefix); pw.print(" extractNativeLibs=");
+ pw.println((ps.pkgFlags & ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS) != 0
+ ? "true" : "false");
pw.print(prefix); pw.print(" primaryCpuAbi="); pw.println(ps.primaryCpuAbiString);
pw.print(prefix); pw.print(" secondaryCpuAbi="); pw.println(ps.secondaryCpuAbiString);
}
@@ -5544,32 +5460,11 @@ public final class Settings {
// Make sure we do not
mHandler.removeMessages(userId);
- for (SettingBase sb : mPackages.values()) {
- revokeRuntimePermissionsAndClearFlags(sb, userId);
- }
-
- for (SettingBase sb : mSharedUsers.values()) {
- revokeRuntimePermissionsAndClearFlags(sb, userId);
- }
-
mPermissionUpgradeNeeded.delete(userId);
mVersions.delete(userId);
mFingerprints.remove(userId);
}
- private void revokeRuntimePermissionsAndClearFlags(SettingBase sb, int userId) {
- PermissionsState permissionsState = sb.getPermissionsState();
- for (PermissionState permissionState
- : permissionsState.getRuntimePermissionStates(userId)) {
- BasePermission bp = mPermissions.getPermission(permissionState.getName());
- if (bp != null) {
- permissionsState.revokeRuntimePermission(bp, userId);
- permissionsState.updatePermissionFlags(bp, userId,
- PackageManager.MASK_PERMISSION_FLAGS_ALL, 0);
- }
- }
- }
-
public void deleteUserRuntimePermissionsFile(int userId) {
mPersistence.deleteForUser(UserHandle.of(userId));
}
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index f9bf54a11df0..ac05aabf998f 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -56,6 +56,7 @@ import android.os.UserManagerInternal;
import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;
@@ -84,6 +85,7 @@ import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@@ -650,6 +652,7 @@ public class StagingManager {
try {
if (hasApex) {
checkInstallationOfApkInApexSuccessful(session);
+ checkDuplicateApkInApex(session);
snapshotAndRestoreForApexSession(session);
Slog.i(TAG, "APEX packages in session " + session.sessionId
+ " were successfully activated. Proceeding with APK packages, if any");
@@ -829,6 +832,40 @@ public class StagingManager {
return null;
}
+ /**
+ * Throws a PackageManagerException if there are duplicate packages in apk and apk-in-apex.
+ */
+ private void checkDuplicateApkInApex(@NonNull PackageInstallerSession session)
+ throws PackageManagerException {
+ if (!session.isMultiPackage()) {
+ return;
+ }
+ final int[] childSessionIds = session.getChildSessionIds();
+ final Set<String> apkNames = new ArraySet<>();
+ synchronized (mStagedSessions) {
+ for (int id : childSessionIds) {
+ final PackageInstallerSession s = mStagedSessions.get(id);
+ if (!isApexSession(s)) {
+ apkNames.add(s.getPackageName());
+ }
+ }
+ }
+ final List<PackageInstallerSession> apexSessions = extractApexSessions(session);
+ for (PackageInstallerSession apexSession : apexSessions) {
+ String packageName = apexSession.getPackageName();
+ for (String apkInApex : mApexManager.getApksInApex(packageName)) {
+ if (!apkNames.add(apkInApex)) {
+ throw new PackageManagerException(
+ SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+ "Package: " + packageName + " in session: "
+ + apexSession.sessionId + " has duplicate apk-in-apex: "
+ + apkInApex, null);
+
+ }
+ }
+ }
+ }
+
private void installApksInSession(@NonNull PackageInstallerSession session)
throws PackageManagerException {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index bf9506ad51f1..f66b4ee5a1a7 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -87,6 +87,7 @@ import android.stats.devicepolicy.DevicePolicyEnums;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
+import android.util.IndentingPrintWriter;
import android.util.IntArray;
import android.util.Slog;
import android.util.SparseArray;
@@ -103,7 +104,6 @@ import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.FrameworkStatsLog;
-import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.internal.widget.LockPatternUtils;
@@ -141,6 +141,7 @@ import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* Service for {@link UserManager}.
@@ -443,6 +444,11 @@ public class UserManagerService extends IUserManager.Stub {
}
};
+ // TODO(b/161915546): remove once userWithName() is fixed / removed
+ // Use to debug / dump when user 0 is allocated at userWithName()
+ public static final boolean DBG_ALLOCATION = false; // DO NOT SUBMIT WITH TRUE
+ public final AtomicInteger mUser0Allocations;
+
/**
* Start an {@link IntentSender} when user is unlocked after disabling quiet mode.
*
@@ -629,6 +635,7 @@ public class UserManagerService extends IUserManager.Stub {
LocalServices.addService(UserManagerInternal.class, mLocalService);
mLockPatternUtils = new LockPatternUtils(mContext);
mUserStates.put(UserHandle.USER_SYSTEM, UserState.STATE_BOOTING);
+ mUser0Allocations = DBG_ALLOCATION ? new AtomicInteger() : null;
}
void systemReady() {
@@ -1310,6 +1317,10 @@ public class UserManagerService extends IUserManager.Stub {
*/
private UserInfo userWithName(UserInfo orig) {
if (orig != null && orig.name == null && orig.id == UserHandle.USER_SYSTEM) {
+ if (DBG_ALLOCATION) {
+ final int number = mUser0Allocations.incrementAndGet();
+ Slog.w(LOG_TAG, "System user instantiated at least " + number + " times");
+ }
UserInfo withName = new UserInfo(orig);
withName.name = getOwnerName();
return withName;
@@ -4786,6 +4797,7 @@ public class UserManagerService extends IUserManager.Stub {
}
}
+ pw.println();
pw.println("Device properties:");
pw.println(" Device owner id:" + mDeviceOwnerUserId);
pw.println();
@@ -4814,12 +4826,9 @@ public class UserManagerService extends IUserManager.Stub {
}
pw.println(']');
}
-
synchronized (mUsersLock) {
- pw.println();
- pw.print("Cached user IDs: ");
+ pw.print(" Cached user IDs: ");
pw.println(Arrays.toString(mUserIds));
- pw.println();
}
} // synchronized (mPackagesLock)
@@ -4835,6 +4844,10 @@ public class UserManagerService extends IUserManager.Stub {
pw.println(" Is split-system user: " + UserManager.isSplitSystemUser());
pw.println(" Is headless-system mode: " + UserManager.isHeadlessSystemUserMode());
pw.println(" User version: " + mUserVersion);
+ pw.println(" Owner name: " + getOwnerName());
+ if (DBG_ALLOCATION) {
+ pw.println(" System user allocations: " + mUser0Allocations.get());
+ }
// Dump UserTypes
pw.println();
@@ -4844,9 +4857,17 @@ public class UserManagerService extends IUserManager.Stub {
mUserTypes.valueAt(i).dump(pw, " ");
}
- // Dump package whitelist
- pw.println();
- mSystemPackageInstaller.dump(pw);
+ // TODO: create IndentingPrintWriter at the beginning of dump() and use the proper
+ // indentation methods instead of explicit printing " "
+ try (IndentingPrintWriter ipw = new IndentingPrintWriter(pw)) {
+
+ // Dump SystemPackageInstaller info
+ ipw.println();
+ mSystemPackageInstaller.dump(ipw);
+
+ // NOTE: pw's not available after this point as it's auto-closed by ipw, so new dump
+ // statements should use ipw below
+ }
}
private static void dumpTimeAgo(PrintWriter pw, StringBuilder sb, long nowTime, long time) {
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 3c1d189dc102..f7e9e34a4702 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -139,6 +139,11 @@ public class UserRestrictionsUtils {
UserManager.DISALLOW_CONFIG_PRIVATE_DNS
});
+ public static final Set<String> DEPRECATED_USER_RESTRICTIONS = Sets.newArraySet(
+ UserManager.DISALLOW_ADD_MANAGED_PROFILE,
+ UserManager.DISALLOW_REMOVE_MANAGED_PROFILE
+ );
+
/**
* Set of user restriction which we don't want to persist.
*/
diff --git a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
index 492b84a0a84b..b95404febf72 100644
--- a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
+++ b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
@@ -28,15 +28,14 @@ import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
+import android.util.IndentingPrintWriter;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
import com.android.server.pm.parsing.pkg.AndroidPackage;
-import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -723,13 +722,7 @@ class UserSystemPackageInstaller {
return userTypeList;
}
- void dump(PrintWriter pw) {
- try (IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ")) {
- dumpIndented(ipw);
- }
- }
-
- private void dumpIndented(IndentingPrintWriter pw) {
+ void dump(IndentingPrintWriter pw) {
final int mode = getWhitelistMode();
pw.println("Whitelisted packages per user type");
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index cfa0449aaf33..962638b4f63c 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -38,7 +38,6 @@ import android.util.Slog;
import com.android.server.pm.DumpState;
import com.android.server.pm.PackageManagerService;
-import com.android.server.pm.PackageSetting;
import com.android.server.pm.PackageSettingBase;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
@@ -420,8 +419,7 @@ public final class BasePermission {
}
public void enforceDeclaredUsedAndRuntimeOrDevelopment(AndroidPackage pkg,
- PackageSetting pkgSetting) {
- final PermissionsState permsState = pkgSetting.getPermissionsState();
+ PermissionsState permsState) {
int index = pkg.getRequestedPermissions().indexOf(name);
if (!permsState.hasRequestedPermission(name) && index == -1) {
throw new SecurityException("Package " + pkg.getPackageName()
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 03771be0ce7c..86d767dd5df4 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -83,6 +83,7 @@ import android.content.pm.PackageParser;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
+import android.content.pm.UserInfo;
import android.content.pm.parsing.component.ParsedPermission;
import android.content.pm.parsing.component.ParsedPermissionGroup;
import android.content.pm.permission.SplitPermissionInfoParcelable;
@@ -120,6 +121,7 @@ import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import android.util.TimingsTraceLog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -140,7 +142,6 @@ import com.android.server.Watchdog;
import com.android.server.pm.ApexManager;
import com.android.server.pm.PackageManagerServiceUtils;
import com.android.server.pm.PackageSetting;
-import com.android.server.pm.SharedUserSetting;
import com.android.server.pm.UserManagerService;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
@@ -225,6 +226,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
/** Internal connection to the user manager */
private final UserManagerInternal mUserManagerInt;
+ /** Maps from App ID to PermissionsState */
+ private final SparseArray<PermissionsState> mAppIdStates = new SparseArray<>();
+
/** Permission controller: User space permission management */
private PermissionControllerManager mPermissionControllerManager;
@@ -669,11 +673,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (pkg == null) {
return 0;
}
- final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
- pkg.getPackageName());
- if (ps == null) {
- return 0;
- }
synchronized (mLock) {
if (mSettings.getPermissionLocked(permName) == null) {
return 0;
@@ -682,7 +681,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
return 0;
}
- PermissionsState permissionsState = ps.getPermissionsState();
+ final PermissionsState permissionsState = getPermissionsState(pkg);
+ if (permissionsState == null) {
+ Slog.e(TAG, "Missing permissions state for " + packageName);
+ return 0;
+ }
return permissionsState.getPermissionFlags(permName, userId);
}
@@ -769,9 +772,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
- final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
- packageName);
- if (pkg == null || ps == null) {
+ if (pkg == null) {
Log.e(TAG, "Unknown package: " + packageName);
return;
}
@@ -787,7 +788,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
throw new IllegalArgumentException("Unknown permission: " + permName);
}
- final PermissionsState permissionsState = ps.getPermissionsState();
+ final PermissionsState permissionsState = getPermissionsState(pkg);
+ if (permissionsState == null) {
+ Slog.e(TAG, "Missing permissions state for " + packageName);
+ return;
+ }
+
final boolean hadState =
permissionsState.getRuntimePermissionState(permName, userId) != null;
if (!hadState) {
@@ -862,12 +868,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final boolean[] changed = new boolean[1];
mPackageManagerInt.forEachPackage(pkg -> {
- final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
- pkg.getPackageName());
- if (ps == null) {
+ final PermissionsState permissionsState = getPermissionsState(pkg);
+ if (permissionsState == null) {
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName());
return;
}
- final PermissionsState permissionsState = ps.getPermissionsState();
changed[0] |= permissionsState.updatePermissionFlagsForAllPermissions(
userId, effectiveFlagMask, effectiveFlagValues);
mOnPermissionChangeListeners.onPermissionsChanged(pkg.getUid());
@@ -879,7 +884,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
- public int checkPermission(String permName, String pkgName, int userId) {
+ public int checkPermission(String permName, String pkgName, @UserIdInt int userId) {
// Not using Objects.requireNonNull() here for compatibility reasons.
if (permName == null || pkgName == null) {
return PackageManager.PERMISSION_DENIED;
@@ -921,12 +926,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
final int uid = UserHandle.getUid(userId, pkg.getUid());
- final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
- pkg.getPackageName());
- if (ps == null) {
+ final PermissionsState permissionsState = getPermissionsState(pkg);
+ if (permissionsState == null) {
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName());
return PackageManager.PERMISSION_DENIED;
}
- final PermissionsState permissionsState = ps.getPermissionsState();
if (checkSinglePermissionInternal(uid, permissionsState, permissionName)) {
return PackageManager.PERMISSION_GRANTED;
@@ -1137,9 +1141,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final long identity = Binder.clearCallingIdentity();
try {
- final PermissionsState permissionsState =
- PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt, pkg);
+ final PermissionsState permissionsState = getPermissionsState(pkg);
if (permissionsState == null) {
+ Slog.e(TAG, "Missing permissions state for " + packageName);
return null;
}
@@ -1449,7 +1453,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
- bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg, ps);
+ final PermissionsState permissionsState = getPermissionsState(pkg);
+ if (permissionsState == null) {
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName());
+ return;
+ }
+
+ bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg, permissionsState);
// If a permission review is required for legacy apps we represent
// their permissions as always granted runtime ones since we need
@@ -1462,8 +1472,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final int uid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.getUid()));
- final PermissionsState permissionsState = ps.getPermissionsState();
-
final int flags = permissionsState.getPermissionFlags(permName, userId);
if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
Log.e(TAG, "Cannot grant system fixed permission "
@@ -1597,9 +1605,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
"revokeRuntimePermission");
final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
- final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
- packageName);
- if (pkg == null || ps == null) {
+ if (pkg == null) {
Log.e(TAG, "Unknown package: " + packageName);
return;
}
@@ -1611,7 +1617,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
throw new IllegalArgumentException("Unknown permission: " + permName);
}
- bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg, ps);
+ final PermissionsState permissionsState = getPermissionsState(pkg);
+ if (permissionsState == null) {
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName());
+ return;
+ }
+
+ bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg, permissionsState);
// If a permission review is required for legacy apps we represent
// their permissions as always granted runtime ones since we need
@@ -1622,8 +1634,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return;
}
- final PermissionsState permissionsState = ps.getPermissionsState();
-
final int flags = permissionsState.getPermissionFlags(permName, userId);
// Only the system may revoke SYSTEM_FIXED permissions.
if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0
@@ -2454,14 +2464,36 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
+ private void onUserRemoved(@UserIdInt int userId) {
+ synchronized (mLock) {
+ final int appIdStatesSize = mAppIdStates.size();
+ for (int i = 0; i < appIdStatesSize; i++) {
+ PermissionsState permissionsState = mAppIdStates.valueAt(i);
+ for (PermissionState permissionState
+ : permissionsState.getRuntimePermissionStates(userId)) {
+ BasePermission bp = mSettings.getPermission(permissionState.getName());
+ if (bp != null) {
+ permissionsState.revokeRuntimePermission(bp, userId);
+ permissionsState.updatePermissionFlags(bp, userId,
+ PackageManager.MASK_PERMISSION_FLAGS_ALL, 0);
+ }
+ }
+ }
+ }
+ }
+
@NonNull
private Set<String> getGrantedPermissions(@NonNull String packageName,
@UserIdInt int userId) {
- final PackageSetting ps = mPackageManagerInt.getPackageSetting(packageName);
- if (ps == null) {
+ final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
+ if (pkg == null) {
+ return null;
+ }
+ final PermissionsState permissionsState = getPermissionsState(pkg);
+ if (permissionsState == null) {
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName());
return null;
}
- final PermissionsState permissionsState = ps.getPermissionsState();
return permissionsState.getPermissions(userId);
}
@@ -2476,11 +2508,15 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@Nullable
private int[] getPackageGids(@NonNull String packageName, @UserIdInt int userId) {
- final PackageSetting ps = mPackageManagerInt.getPackageSetting(packageName);
- if (ps == null) {
+ final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
+ if (pkg == null) {
+ return null;
+ }
+ final PermissionsState permissionsState = getPermissionsState(pkg);
+ if (permissionsState == null) {
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName());
return null;
}
- final PermissionsState permissionsState = ps.getPermissionsState();
return permissionsState.computeGids(userId);
}
@@ -2518,15 +2554,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (ps == null) {
return;
}
+ final PermissionsState permissionsState = getOrCreatePermissionsState(pkg);
- final PermissionsState permissionsState = ps.getPermissionsState();
-
- final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
+ final int[] userIds = getAllUserIds();
boolean runtimePermissionsRevoked = false;
int[] updatedUserIds = EMPTY_INT_ARRAY;
- for (int userId : currentUserIds) {
+ for (int userId : userIds) {
if (permissionsState.isMissing(userId)) {
Collection<String> requestedPermissions;
int targetSdkVersion;
@@ -2591,8 +2626,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// changed runtime permissions here are promotion of an install to
// runtime and revocation of a runtime from a shared user.
synchronized (mLock) {
- updatedUserIds = revokeUnusedSharedUserPermissionsLocked(ps.getSharedUser(),
- currentUserIds);
+ updatedUserIds = revokeUnusedSharedUserPermissionsLocked(
+ ps.getSharedUser().getPackages(), permissionsState, userIds);
if (!ArrayUtils.isEmpty(updatedUserIds)) {
runtimePermissionsRevoked = true;
}
@@ -2747,7 +2782,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// a runtime permission being downgraded to an install one.
// Also in permission review mode we keep dangerous permissions
// for legacy apps
- for (int userId : currentUserIds) {
+ for (int userId : userIds) {
if (origPermissions.getRuntimePermissionState(
perm, userId) != null) {
// Revoke the runtime permission and clear the flags.
@@ -2770,7 +2805,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
boolean hardRestricted = bp.isHardRestricted();
boolean softRestricted = bp.isSoftRestricted();
- for (int userId : currentUserIds) {
+ for (int userId : userIds) {
// If permission policy is not ready we don't deal with restricted
// permissions as the policy may whitelist some permissions. Once
// the policy is initialized we would re-evaluate permissions.
@@ -2909,7 +2944,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
boolean hardRestricted = bp.isHardRestricted();
boolean softRestricted = bp.isSoftRestricted();
- for (int userId : currentUserIds) {
+ for (int userId : userIds) {
// If permission policy is not ready we don't deal with restricted
// permissions as the policy may whitelist some permissions. Once
// the policy is initialized we would re-evaluate permissions.
@@ -3061,13 +3096,15 @@ public class PermissionManagerService extends IPermissionManager.Stub {
synchronized (mLock) {
updatedUserIds = revokePermissionsNoLongerImplicitLocked(permissionsState, pkg,
- currentUserIds, updatedUserIds);
+ userIds, updatedUserIds);
updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origPermissions,
- permissionsState, pkg, newImplicitPermissions, currentUserIds, updatedUserIds);
- updatedUserIds = checkIfLegacyStorageOpsNeedToBeUpdated(pkg, replace, currentUserIds,
+ permissionsState, pkg, newImplicitPermissions, userIds, updatedUserIds);
+ updatedUserIds = checkIfLegacyStorageOpsNeedToBeUpdated(pkg, replace, userIds,
updatedUserIds);
}
+ // TODO: Kill UIDs whose GIDs or runtime permissions changed. This might be more important
+ // for shared users.
// Persist the runtime permissions state for users with changes. If permissions
// were revoked because no app in the shared user declares them we have to
// write synchronously to avoid losing runtime permissions state.
@@ -3081,6 +3118,25 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
/**
+ * Returns all relevant user ids. This list include the current set of created user ids as well
+ * as pre-created user ids.
+ * @return user ids for created users and pre-created users
+ */
+ private int[] getAllUserIds() {
+ final TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
+ t.traceBegin("getAllUserIds");
+ List<UserInfo> users = UserManagerService.getInstance().getUsers(
+ /*excludePartial=*/ true, /*excludeDying=*/ true, /*excludePreCreated=*/ false);
+ int size = users.size();
+ final int[] userIds = new int[size];
+ for (int i = 0; i < size; i++) {
+ userIds[i] = users.get(i).id;
+ }
+ t.traceEnd();
+ return userIds;
+ }
+
+ /**
* Revoke permissions that are not implicit anymore and that have
* {@link PackageManager#FLAG_PERMISSION_REVOKE_WHEN_REQUESTED} set.
*
@@ -3512,37 +3568,15 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final PackageSetting disabledPs = mPackageManagerInt
.getDisabledSystemPackage(pkg.getPackageName());
final AndroidPackage disabledPkg = disabledPs == null ? null : disabledPs.pkg;
- if (disabledPs != null
- && disabledPs.getPermissionsState().hasInstallPermission(perm)) {
- // If the original was granted this permission, we take
- // that grant decision as read and propagate it to the
- // update.
- if ((privilegedPermission && disabledPs.isPrivileged())
- || (oemPermission && disabledPs.isOem()
- && canGrantOemPermission(disabledPs, perm))) {
- allowed = true;
- }
- } else {
- // The system apk may have been updated with an older
- // version of the one on the data partition, but which
- // granted a new system permission that it didn't have
- // before. In this case we do want to allow the app to
- // now get the new permission if the ancestral apk is
- // privileged to get it.
- if (disabledPs != null && disabledPkg != null
- && isPackageRequestingPermission(disabledPkg, perm)
- && ((privilegedPermission && disabledPs.isPrivileged())
- || (oemPermission && disabledPs.isOem()
- && canGrantOemPermission(disabledPs, perm)))) {
- allowed = true;
- }
+ if (disabledPkg != null && isPackageRequestingPermission(disabledPkg, perm)
+ && ((privilegedPermission && disabledPkg.isPrivileged())
+ || (oemPermission && canGrantOemPermission(disabledPkg,
+ perm)))) {
+ allowed = true;
}
} else {
- final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
- pkg.getPackageName());
allowed = (privilegedPermission && pkg.isPrivileged())
- || (oemPermission && pkg.isOem()
- && canGrantOemPermission(ps, perm));
+ || (oemPermission && canGrantOemPermission(pkg, perm));
}
// In any case, don't grant a privileged permission to privileged vendor apps, if
// the permission's protectionLevel does not have the extra 'vendorPrivileged'
@@ -3693,16 +3727,16 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return false;
}
- private static boolean canGrantOemPermission(PackageSetting ps, String permission) {
- if (!ps.isOem()) {
+ private static boolean canGrantOemPermission(AndroidPackage pkg, String permission) {
+ if (!pkg.isOem()) {
return false;
}
// all oem permissions must explicitly be granted or denied
final Boolean granted =
- SystemConfig.getInstance().getOemPermissions(ps.name).get(permission);
+ SystemConfig.getInstance().getOemPermissions(pkg.getPackageName()).get(permission);
if (granted == null) {
throw new IllegalStateException("OEM permission" + permission + " requested by package "
- + ps.name + " must be explicitly declared granted or not");
+ + pkg.getPackageName() + " must be explicitly declared granted or not");
}
return Boolean.TRUE == granted;
}
@@ -3715,12 +3749,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
// Legacy apps have the permission and get user consent on launch.
- final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
- pkg.getPackageName());
- if (ps == null) {
+ final PermissionsState permissionsState = getPermissionsState(pkg);
+ if (permissionsState == null) {
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName());
return false;
}
- final PermissionsState permissionsState = ps.getPermissionsState();
return permissionsState.isPermissionReviewRequired(userId);
}
@@ -3745,14 +3778,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private void grantRequestedRuntimePermissionsForUser(AndroidPackage pkg, int userId,
String[] grantedPermissions, int callingUid, PermissionCallback callback) {
- PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
- pkg.getPackageName());
- if (ps == null) {
+ final PermissionsState permissionsState = getPermissionsState(pkg);
+ if (permissionsState == null) {
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName());
return;
}
- PermissionsState permissionsState = ps.getPermissionsState();
-
final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
| PackageManager.FLAG_PERMISSION_POLICY_FIXED;
@@ -3796,9 +3827,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private void setWhitelistedRestrictedPermissionsForUsers(@NonNull AndroidPackage pkg,
@UserIdInt int[] userIds, @Nullable List<String> permissions, int callingUid,
@PermissionWhitelistFlags int whitelistFlags, PermissionCallback callback) {
- final PermissionsState permissionsState =
- PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt, pkg);
+ final PermissionsState permissionsState = getPermissionsState(pkg);
if (permissionsState == null) {
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName());
return;
}
@@ -3916,9 +3947,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
for (int j = 0; j < oldGrantedCount; j++) {
final String permission = oldPermsForUser.valueAt(j);
// Sometimes we create a new permission state instance during update.
- final PermissionsState newPermissionsState =
- PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt,
- pkg);
+ final PermissionsState newPermissionsState = getPermissionsState(pkg);
+ if (permissionsState == null) {
+ Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName());
+ continue;
+ }
if (!newPermissionsState.hasPermission(permission, userId)) {
callback.onPermissionRevoked(pkg.getUid(), userId, null);
break;
@@ -3930,10 +3963,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@GuardedBy("mLock")
private int[] revokeUnusedSharedUserPermissionsLocked(
- SharedUserSetting suSetting, int[] allUserIds) {
+ List<AndroidPackage> pkgList, PermissionsState permissionsState, int[] allUserIds) {
// Collect all used permissions in the UID
final ArraySet<String> usedPermissions = new ArraySet<>();
- final List<AndroidPackage> pkgList = suSetting.getPackages();
if (pkgList == null || pkgList.size() == 0) {
return EmptyArray.INT;
}
@@ -3951,7 +3983,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
- PermissionsState permissionsState = suSetting.getPermissionsState();
// Prune install permissions
List<PermissionState> installPermStates = permissionsState.getInstallPermissionStates();
final int installPermCount = installPermStates.size();
@@ -4237,12 +4268,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
} else {
mPackageManagerInt.forEachPackage(p -> {
- PackageSetting ps = mPackageManagerInt.getPackageSetting(
- p.getPackageName());
- if (ps == null) {
+ final PermissionsState permissionsState = getPermissionsState(p);
+ if (permissionsState == null) {
+ Slog.e(TAG, "Missing permissions state for " + p.getPackageName());
return;
}
- PermissionsState permissionsState = ps.getPermissionsState();
if (permissionsState.getInstallPermissionState(bp.getName()) != null) {
permissionsState.revokeInstallPermission(bp);
permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
@@ -4649,6 +4679,66 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return mBackgroundPermissions;
}
+ @Nullable
+ private PermissionsState getPermissionsState(@NonNull AndroidPackage pkg) {
+ return getPermissionsState(pkg.getUid());
+ }
+
+ @Nullable
+ private PermissionsState getPermissionsState(int appId) {
+ synchronized (mLock) {
+ return mAppIdStates.get(appId);
+ }
+ }
+
+ @Nullable
+ private PermissionsState getOrCreatePermissionsState(@NonNull AndroidPackage pkg) {
+ return getOrCreatePermissionsState(pkg.getUid());
+ }
+
+ @Nullable
+ private PermissionsState getOrCreatePermissionsState(int appId) {
+ synchronized (mLock) {
+ PermissionsState state = mAppIdStates.get(appId);
+ if (state == null) {
+ state = new PermissionsState();
+ mAppIdStates.put(appId, state);
+ }
+ return state;
+ }
+ }
+
+ private void removePermissionsState(int appId) {
+ synchronized (mLock) {
+ mAppIdStates.remove(appId);
+ }
+ }
+
+ private void readPermissionsStateFromPackageSettings() {
+ mPackageManagerInt.forEachPackageSetting(ps -> {
+ synchronized (mLock) {
+ final int appId = ps.pkg.getUid();
+ if (!mAppIdStates.contains(appId)) {
+ mAppIdStates.put(appId, new PermissionsState(ps.getPermissionsState()));
+ }
+ }
+ });
+ }
+
+ private void writePermissionsStateToPackageSettings() {
+ mPackageManagerInt.forEachPackageSetting(ps -> {
+ synchronized (mLock) {
+ final int appId = ps.pkg.getUid();
+ final PermissionsState permissionsState = mAppIdStates.get(appId);
+ if (permissionsState == null) {
+ Slog.e(TAG, "Missing permissions state for " + ps.pkg.getPackageName());
+ return;
+ }
+ ps.getPermissionsState().copyFrom(permissionsState);
+ }
+ });
+ }
+
private class PermissionManagerServiceInternalImpl extends PermissionManagerServiceInternal {
@Override
public void systemReady() {
@@ -4680,6 +4770,22 @@ public class PermissionManagerService extends IPermissionManager.Stub {
public void removeAllPermissions(AndroidPackage pkg, boolean chatty) {
PermissionManagerService.this.removeAllPermissions(pkg, chatty);
}
+ @Override
+ public void readPermissionsStateFromPackageSettingsTEMP() {
+ PermissionManagerService.this.readPermissionsStateFromPackageSettings();
+ }
+ @Override
+ public void writePermissionsStateToPackageSettingsTEMP() {
+ PermissionManagerService.this.writePermissionsStateToPackageSettings();
+ }
+ @Override
+ public void onUserRemoved(@UserIdInt int userId) {
+ PermissionManagerService.this.onUserRemoved(userId);
+ }
+ @Override
+ public void removePermissionsStateTEMP(int appId) {
+ PermissionManagerService.this.removePermissionsState(appId);
+ }
@NonNull
@Override
public Set<String> getGrantedPermissions(@NonNull String packageName,
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index cfa371ddbad3..5c7ff1f9a1ad 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -265,6 +265,37 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
public abstract void removeAllPermissions(@NonNull AndroidPackage pkg, boolean chatty);
/**
+ * Read {@code PermissionsState} from package settings.
+ *
+ * TODO(zhanghai): This is a temporary method because we should not expose
+ * {@code PackageSetting} which is a implementation detail that permission should not know.
+ * Instead, it should retrieve the legacy state via a defined API.
+ */
+ public abstract void readPermissionsStateFromPackageSettingsTEMP();
+
+ /**
+ * Write {@code PermissionsState} from to settings.
+ *
+ * TODO(zhanghai): This is a temporary method and should be removed once we migrated persistence
+ * for permission.
+ */
+ public abstract void writePermissionsStateToPackageSettingsTEMP();
+
+ /**
+ * Notify that a user has been removed and its permission state should be removed as well.
+ */
+ public abstract void onUserRemoved(@UserIdInt int userId);
+
+ /**
+ * Remove the {@code PermissionsState} associated with an app ID, called the same time as the
+ * removal of a {@code PackageSetitng}.
+ *
+ * TODO(zhanghai): This is a temporary method before we figure out a way to get notified of app
+ * ID removal via API.
+ */
+ public abstract void removePermissionsStateTEMP(int appId);
+
+ /**
* Get all the permissions granted to a package.
*/
@NonNull
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 4d48a2e63b30..ae2b040d0a89 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -89,7 +89,7 @@ import java.util.concurrent.ExecutionException;
public final class PermissionPolicyService extends SystemService {
private static final String LOG_TAG = PermissionPolicyService.class.getSimpleName();
private static final boolean DEBUG = false;
- private static final long USER_SENSITIVE_UPDATE_DELAY_MS = 10000;
+ private static final long USER_SENSITIVE_UPDATE_DELAY_MS = 60000;
private final Object mLock = new Object();
@@ -283,6 +283,11 @@ public final class PermissionPolicyService extends SystemService {
manager.updateUserSensitiveForApp(uid);
}
}, UserHandle.ALL, intentFilter, null, null);
+
+ PermissionControllerManager manager = new PermissionControllerManager(
+ getUserContext(getContext(), Process.myUserHandle()), FgThread.getHandler());
+ FgThread.getHandler().postDelayed(manager::updateUserSensitive,
+ USER_SENSITIVE_UPDATE_DELAY_MS);
}
/**
@@ -425,8 +430,7 @@ public final class PermissionPolicyService extends SystemService {
throw new IllegalStateException(e);
}
- FgThread.getHandler().postDelayed(permissionControllerManager::updateUserSensitive,
- USER_SENSITIVE_UPDATE_DELAY_MS);
+ permissionControllerManager.updateUserSensitive();
packageManagerInternal.updateRuntimePermissionsFingerprint(userId);
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index fa3bcb6b98eb..548cd70de4d1 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -450,7 +450,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
volatile int mPendingWakeKey = PENDING_KEY_NULL;
int mRecentAppsHeldModifiers;
- boolean mLanguageSwitchKeyPressed;
int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT;
boolean mHaveBuiltInKeyboard;
@@ -2938,12 +2937,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
return -1;
}
- if (mLanguageSwitchKeyPressed && !down
- && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
- || keyCode == KeyEvent.KEYCODE_SPACE)) {
- mLanguageSwitchKeyPressed = false;
- return -1;
- }
if (isValidGlobalKey(keyCode)
&& mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
index ef4954aa4e4c..ae0db4419080 100644
--- a/services/core/java/com/android/server/power/ThermalManagerService.java
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -200,7 +200,7 @@ public class ThermalManagerService extends SystemService {
final int count = mTemperatureMap.size();
for (int i = 0; i < count; i++) {
Temperature t = mTemperatureMap.valueAt(i);
- if (t.getStatus() >= newStatus) {
+ if (t.getType() == Temperature.TYPE_SKIN && t.getStatus() >= newStatus) {
newStatus = t.getStatus();
}
}
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index 2a74b3d23829..5aedfc19028b 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -28,8 +28,6 @@ import static android.os.Process.SYSTEM_UID;
import android.Manifest.permission;
import android.annotation.NonNull;
import android.app.AppOpsManager;
-import android.app.role.OnRoleHoldersChangedListener;
-import android.app.role.RoleManager;
import android.app.slice.ISliceManager;
import android.app.slice.SliceSpec;
import android.app.usage.UsageStatsManagerInternal;
@@ -41,9 +39,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
import android.content.pm.ProviderInfo;
-import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
@@ -65,7 +61,6 @@ import com.android.internal.app.AssistUtils;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -77,10 +72,7 @@ import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.List;
import java.util.Objects;
-import java.util.concurrent.Executor;
-import java.util.function.Supplier;
public class SliceManagerService extends ISliceManager.Stub {
@@ -88,16 +80,13 @@ public class SliceManagerService extends ISliceManager.Stub {
private final Object mLock = new Object();
private final Context mContext;
- private final PackageManagerInternal mPackageManagerInternal;
private final AppOpsManager mAppOps;
private final AssistUtils mAssistUtils;
@GuardedBy("mLock")
private final ArrayMap<Uri, PinnedSliceState> mPinnedSlicesByUri = new ArrayMap<>();
@GuardedBy("mLock")
- private final SparseArray<PackageMatchingCache> mAssistantLookup = new SparseArray<>();
- @GuardedBy("mLock")
- private final SparseArray<PackageMatchingCache> mHomeLookup = new SparseArray<>();
+ private final SparseArray<String> mLastAssistantPackage = new SparseArray<>();
private final Handler mHandler;
private final SlicePermissionManager mPermissions;
@@ -110,8 +99,6 @@ public class SliceManagerService extends ISliceManager.Stub {
@VisibleForTesting
SliceManagerService(Context context, Looper looper) {
mContext = context;
- mPackageManagerInternal = Objects.requireNonNull(
- LocalServices.getService(PackageManagerInternal.class));
mAppOps = context.getSystemService(AppOpsManager.class);
mAssistUtils = new AssistUtils(context);
mHandler = new Handler(looper);
@@ -124,7 +111,6 @@ public class SliceManagerService extends ISliceManager.Stub {
filter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addDataScheme("package");
- mRoleObserver = new RoleObserver();
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
}
@@ -174,8 +160,7 @@ public class SliceManagerService extends ISliceManager.Stub {
mHandler.post(() -> {
if (slicePkg != null && !Objects.equals(pkg, slicePkg)) {
mAppUsageStats.reportEvent(slicePkg, user,
- isAssistant(pkg, user) || isDefaultHomeApp(pkg, user)
- ? SLICE_PINNED_PRIV : SLICE_PINNED);
+ isAssistant(pkg, user) ? SLICE_PINNED_PRIV : SLICE_PINNED);
}
});
}
@@ -440,38 +425,19 @@ public class SliceManagerService extends ISliceManager.Stub {
private boolean hasFullSliceAccess(String pkg, int userId) {
long ident = Binder.clearCallingIdentity();
try {
- boolean ret = isDefaultHomeApp(pkg, userId) || isAssistant(pkg, userId)
- || isGrantedFullAccess(pkg, userId);
- return ret;
+ return isAssistant(pkg, userId) || isGrantedFullAccess(pkg, userId);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
private boolean isAssistant(String pkg, int userId) {
- return getAssistantMatcher(userId).matches(pkg);
- }
-
- private boolean isDefaultHomeApp(String pkg, int userId) {
- return getHomeMatcher(userId).matches(pkg);
- }
-
- private PackageMatchingCache getAssistantMatcher(int userId) {
- PackageMatchingCache matcher = mAssistantLookup.get(userId);
- if (matcher == null) {
- matcher = new PackageMatchingCache(() -> getAssistant(userId));
- mAssistantLookup.put(userId, matcher);
- }
- return matcher;
- }
-
- private PackageMatchingCache getHomeMatcher(int userId) {
- PackageMatchingCache matcher = mHomeLookup.get(userId);
- if (matcher == null) {
- matcher = new PackageMatchingCache(() -> getDefaultHome(userId));
- mHomeLookup.put(userId, matcher);
+ if (pkg == null) return false;
+ if (!pkg.equals(mLastAssistantPackage.get(userId))) {
+ // Failed on cached value, try updating.
+ mLastAssistantPackage.put(userId, getAssistant(userId));
}
- return matcher;
+ return pkg.equals(mLastAssistantPackage.get(userId));
}
private String getAssistant(int userId) {
@@ -482,111 +448,6 @@ public class SliceManagerService extends ISliceManager.Stub {
return cn.getPackageName();
}
- /**
- * A cached value of the default home app
- */
- private String mCachedDefaultHome = null;
-
- // Based on getDefaultHome in ShortcutService.
- // TODO: Unify if possible
- @VisibleForTesting
- protected String getDefaultHome(int userId) {
-
- // Set VERIFY to true to run the cache in "shadow" mode for cache
- // testing. Do not commit set to true;
- final boolean VERIFY = false;
-
- if (mCachedDefaultHome != null) {
- if (!VERIFY) {
- return mCachedDefaultHome;
- }
- }
-
- final long token = Binder.clearCallingIdentity();
- try {
- final List<ResolveInfo> allHomeCandidates = new ArrayList<>();
-
- // Default launcher from package manager.
- final ComponentName defaultLauncher = mPackageManagerInternal
- .getHomeActivitiesAsUser(allHomeCandidates, userId);
-
- ComponentName detected = defaultLauncher;
-
- // Cache the default launcher. It is not a problem if the
- // launcher is null - eventually, the default launcher will be
- // set to something non-null.
- mCachedDefaultHome = ((detected != null) ? detected.getPackageName() : null);
-
- if (detected == null) {
- // If we reach here, that means it's the first check since the user was created,
- // and there's already multiple launchers and there's no default set.
- // Find the system one with the highest priority.
- // (We need to check the priority too because of FallbackHome in Settings.)
- // If there's no system launcher yet, then no one can access slices, until
- // the user explicitly sets one.
- final int size = allHomeCandidates.size();
-
- int lastPriority = Integer.MIN_VALUE;
- for (int i = 0; i < size; i++) {
- final ResolveInfo ri = allHomeCandidates.get(i);
- if (!ri.activityInfo.applicationInfo.isSystemApp()) {
- continue;
- }
- if (ri.priority < lastPriority) {
- continue;
- }
- detected = ri.activityInfo.getComponentName();
- lastPriority = ri.priority;
- }
- }
- final String ret = ((detected != null) ? detected.getPackageName() : null);
- if (VERIFY) {
- if (mCachedDefaultHome != null && !mCachedDefaultHome.equals(ret)) {
- Slog.e(TAG, "getDefaultHome() cache failure, is " +
- mCachedDefaultHome + " should be " + ret);
- }
- }
- return ret;
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- public void invalidateCachedDefaultHome() {
- mCachedDefaultHome = null;
- }
-
- /**
- * Listen for changes in the roles, and invalidate the cached default
- * home as necessary.
- */
- private RoleObserver mRoleObserver;
-
- class RoleObserver implements OnRoleHoldersChangedListener {
- private RoleManager mRm;
- private final Executor mExecutor;
-
- RoleObserver() {
- mExecutor = mContext.getMainExecutor();
- register();
- }
-
- public void register() {
- mRm = mContext.getSystemService(RoleManager.class);
- if (mRm != null) {
- mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.ALL);
- invalidateCachedDefaultHome();
- }
- }
-
- @Override
- public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
- if (RoleManager.ROLE_HOME.equals(roleName)) {
- invalidateCachedDefaultHome();
- }
- }
- }
-
private boolean isGrantedFullAccess(String pkg, int userId) {
return mPermissions.hasFullAccess(pkg, userId);
}
@@ -635,30 +496,6 @@ public class SliceManagerService extends ISliceManager.Stub {
return mPermissions.getAllPackagesGranted(pkg);
}
- /**
- * Holder that caches a package that has access to a slice.
- */
- static class PackageMatchingCache {
-
- private final Supplier<String> mPkgSource;
- private String mCurrentPkg;
-
- public PackageMatchingCache(Supplier<String> pkgSource) {
- mPkgSource = pkgSource;
- }
-
- public boolean matches(String pkgCandidate) {
- if (pkgCandidate == null) return false;
-
- if (Objects.equals(pkgCandidate, mCurrentPkg)) {
- return true;
- }
- // Failed on cached value, try updating.
- mCurrentPkg = mPkgSource.get();
- return Objects.equals(pkgCandidate, mCurrentPkg);
- }
- }
-
public static class Lifecycle extends SystemService {
private SliceManagerService mService;
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java
index c2b0d1067e38..0ca36e0fc258 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java
@@ -72,6 +72,10 @@ public final class TimeZoneDetectorCallbackImpl implements TimeZoneDetectorStrat
builder.setConfigureAutoDetectionEnabled(CAPABILITY_POSSESSED);
}
+ // TODO(b/149014708) Replace this with real logic when the settings storage is fully
+ // implemented.
+ builder.setConfigureGeoDetectionEnabled(CAPABILITY_NOT_SUPPORTED);
+
// The ability to make manual time zone suggestions can also be restricted by policy. With
// the current logic above, this could lead to a situation where a device hardware does not
// support auto detection, the device has been forced into "auto" mode by an admin and the
@@ -90,6 +94,7 @@ public final class TimeZoneDetectorCallbackImpl implements TimeZoneDetectorStrat
public TimeZoneConfiguration getConfiguration(@UserIdInt int userId) {
return new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(isAutoDetectionEnabled())
+ .setGeoDetectionEnabled(isGeoDetectionEnabled())
.build();
}
@@ -105,8 +110,11 @@ public final class TimeZoneDetectorCallbackImpl implements TimeZoneDetectorStrat
// detection: if we wrote it down then we'd set the default explicitly. That might influence
// what happens on later releases that do support auto detection on the same hardware.
if (isAutoDetectionSupported()) {
- final int value = configuration.isAutoDetectionEnabled() ? 1 : 0;
- Settings.Global.putInt(mCr, Settings.Global.AUTO_TIME_ZONE, value);
+ final int autoEnabledValue = configuration.isAutoDetectionEnabled() ? 1 : 0;
+ Settings.Global.putInt(mCr, Settings.Global.AUTO_TIME_ZONE, autoEnabledValue);
+
+ final boolean geoTzDetectionEnabledValue = configuration.isGeoDetectionEnabled();
+ // TODO(b/149014708) Write this down to user-scoped settings once implemented.
}
}
@@ -126,6 +134,14 @@ public final class TimeZoneDetectorCallbackImpl implements TimeZoneDetectorStrat
}
@Override
+ public boolean isGeoDetectionEnabled() {
+ // TODO(b/149014708) Read this from user-scoped settings once implemented. The user's
+ // location toggle will act as an override for this setting, i.e. so that the setting will
+ // return false if the location toggle is disabled.
+ return false;
+ }
+
+ @Override
public boolean isDeviceTimeZoneInitialized() {
// timezone.equals("GMT") will be true and only true if the time zone was
// set to a default value by the system server (when starting, system server
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java
index 3d9ec6475a8b..fb7a73d12632 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java
@@ -22,6 +22,7 @@ import android.annotation.NonNull;
* The internal (in-process) system server API for the {@link
* com.android.server.timezonedetector.TimeZoneDetectorService}.
*
+ * <p>The methods on this class can be called from any thread.
* @hide
*/
public interface TimeZoneDetectorInternal extends Dumpable.Container {
@@ -29,7 +30,7 @@ public interface TimeZoneDetectorInternal extends Dumpable.Container {
/**
* Suggests the current time zone, determined using geolocation, to the detector. The
* detector may ignore the signal based on system settings, whether better information is
- * available, and so on.
+ * available, and so on. This method may be implemented asynchronously.
*/
void suggestGeolocationTimeZone(@NonNull GeolocationTimeZoneSuggestion timeZoneSuggestion);
}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java
index 4464f7d136e3..15412a0d14a1 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java
@@ -58,6 +58,7 @@ public final class TimeZoneDetectorInternalImpl implements TimeZoneDetectorInter
@NonNull GeolocationTimeZoneSuggestion timeZoneSuggestion) {
Objects.requireNonNull(timeZoneSuggestion);
+ // All strategy calls must take place on the mHandler thread.
mHandler.post(
() -> mTimeZoneDetectorStrategy.suggestGeolocationTimeZone(timeZoneSuggestion));
}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
index 7467439905eb..d81f949742bd 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
@@ -130,6 +130,10 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
service.handleAutoTimeZoneConfigChanged();
}
});
+ // TODO(b/149014708) Listen for changes to geolocation time zone detection enabled config.
+ // This should also include listening to the current user and the current user's location
+ // toggle since the config is user-scoped and the location toggle overrides the geolocation
+ // time zone enabled setting.
return service;
}
@@ -280,7 +284,7 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
void handleConfigurationChanged() {
// Note: we could trigger an async time zone detection operation here via a call to
- // handleAutoTimeZoneDetectionChanged(), but that is triggered in response to the underlying
+ // handleAutoTimeZoneConfigChanged(), but that is triggered in response to the underlying
// setting value changing so it is currently unnecessary. If we get to a point where all
// configuration changes are guaranteed to happen in response to an updateConfiguration()
// call, then we can remove that path and call it here instead.
@@ -288,7 +292,6 @@ public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub
// Configuration has changed, but each user may have a different view of the configuration.
// It's possible that this will cause unnecessary notifications but that shouldn't be a
// problem.
-
synchronized (mConfigurationListeners) {
final int userCount = mConfigurationListeners.size();
for (int userIndex = 0; userIndex < userCount; userIndex++) {
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
index f947a6554412..c5b7e39f4fef 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
@@ -30,9 +30,9 @@ import android.util.IndentingPrintWriter;
* <p>The strategy uses suggestions to decide whether to modify the device's time zone setting
* and what to set it to.
*
- * <p>Most calls will be handled by a single thread but that is not true for all calls. For example
- * {@link #dump(IndentingPrintWriter, String[])}) may be called on a different thread so
- * implementations mustvhandle thread safety.
+ * <p>Most calls will be handled by a single thread, but that is not true for all calls. For example
+ * {@link #dump(IndentingPrintWriter, String[])}) may be called on a different thread concurrently
+ * with other operations so implementations must still handle thread safety.
*
* @hide
*/
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
index 9c36c3921e3e..d1369a289428 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
@@ -23,6 +23,7 @@ import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_S
import static android.app.timezonedetector.TimeZoneCapabilities.CAPABILITY_NOT_APPLICABLE;
import static android.app.timezonedetector.TimeZoneCapabilities.CAPABILITY_POSSESSED;
import static android.app.timezonedetector.TimeZoneConfiguration.PROPERTY_AUTO_DETECTION_ENABLED;
+import static android.app.timezonedetector.TimeZoneConfiguration.PROPERTY_GEO_DETECTION_ENABLED;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -98,6 +99,12 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
boolean isAutoDetectionEnabled();
/**
+ * Returns whether geolocation can be used for time zone detection when {@link
+ * #isAutoDetectionEnabled()} returns {@code true}.
+ */
+ boolean isGeoDetectionEnabled();
+
+ /**
* Returns true if the device has had an explicit time zone set.
*/
boolean isDeviceTimeZoneInitialized();
@@ -200,7 +207,15 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
*/
@GuardedBy("this")
private ArrayMapWithHistory<Integer, QualifiedTelephonyTimeZoneSuggestion>
- mSuggestionBySlotIndex = new ArrayMapWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
+ mTelephonySuggestionsBySlotIndex =
+ new ArrayMapWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
+
+ /**
+ * The latest geolocation suggestion received.
+ */
+ @GuardedBy("this")
+ private ReferenceWithHistory<GeolocationTimeZoneSuggestion> mLatestGeoLocationSuggestion =
+ new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
@GuardedBy("this")
private final List<Dumpable> mDumpables = new ArrayList<>();
@@ -284,17 +299,26 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
private static boolean containsAutoTimeDetectionProperties(
@NonNull TimeZoneConfiguration configuration) {
- return configuration.hasProperty(PROPERTY_AUTO_DETECTION_ENABLED);
+ return configuration.hasProperty(PROPERTY_AUTO_DETECTION_ENABLED)
+ || configuration.hasProperty(PROPERTY_GEO_DETECTION_ENABLED);
}
@Override
public synchronized void suggestGeolocationTimeZone(
@NonNull GeolocationTimeZoneSuggestion suggestion) {
+ if (DBG) {
+ Slog.d(LOG_TAG, "Geolocation suggestion received. newSuggestion=" + suggestion);
+ }
+
Objects.requireNonNull(suggestion);
+ mLatestGeoLocationSuggestion.set(suggestion);
- // TODO Implement this.
- throw new UnsupportedOperationException(
- "Geo-location time zone detection is not currently implemented");
+ // Now perform auto time zone detection. The new suggestion may be used to modify the time
+ // zone setting.
+ if (mCallback.isGeoDetectionEnabled()) {
+ String reason = "New geolocation time zone suggested. suggestion=" + suggestion;
+ doAutoTimeZoneDetection(reason);
+ }
}
@Override
@@ -332,12 +356,14 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
new QualifiedTelephonyTimeZoneSuggestion(suggestion, score);
// Store the suggestion against the correct slotIndex.
- mSuggestionBySlotIndex.put(suggestion.getSlotIndex(), scoredSuggestion);
+ mTelephonySuggestionsBySlotIndex.put(suggestion.getSlotIndex(), scoredSuggestion);
// Now perform auto time zone detection. The new suggestion may be used to modify the time
// zone setting.
- String reason = "New telephony time suggested. suggestion=" + suggestion;
- doAutoTimeZoneDetection(reason);
+ if (!mCallback.isGeoDetectionEnabled()) {
+ String reason = "New telephony time zone suggested. suggestion=" + suggestion;
+ doAutoTimeZoneDetection(reason);
+ }
}
private static int scoreTelephonySuggestion(@NonNull TelephonyTimeZoneSuggestion suggestion) {
@@ -363,9 +389,7 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
}
/**
- * Finds the best available time zone suggestion from all slotIndexes. If it is high-enough
- * quality and automatic time zone detection is enabled then it will be set on the device. The
- * outcome can be that this strategy becomes / remains un-opinionated and nothing is set.
+ * Performs automatic time zone detection.
*/
@GuardedBy("this")
private void doAutoTimeZoneDetection(@NonNull String detectionReason) {
@@ -374,6 +398,62 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
return;
}
+ // Use the right suggestions based on the current configuration. This check is potentially
+ // race-prone until this value is set via a call to TimeZoneDetectorStrategy.
+ if (mCallback.isGeoDetectionEnabled()) {
+ doGeolocationTimeZoneDetection(detectionReason);
+ } else {
+ doTelephonyTimeZoneDetection(detectionReason);
+ }
+ }
+
+ /**
+ * Detects the time zone using the latest available geolocation time zone suggestion, if one is
+ * available. The outcome can be that this strategy becomes / remains un-opinionated and nothing
+ * is set.
+ */
+ @GuardedBy("this")
+ private void doGeolocationTimeZoneDetection(@NonNull String detectionReason) {
+ GeolocationTimeZoneSuggestion latestGeolocationSuggestion =
+ mLatestGeoLocationSuggestion.get();
+ if (latestGeolocationSuggestion == null) {
+ return;
+ }
+
+ List<String> zoneIds = latestGeolocationSuggestion.getZoneIds();
+ if (zoneIds == null || zoneIds.isEmpty()) {
+ // This means the client has become uncertain about the time zone or it is certain there
+ // is no known zone. In either case we must leave the existing time zone setting as it
+ // is.
+ return;
+ }
+
+ // GeolocationTimeZoneSuggestion has no measure of quality. We assume all suggestions are
+ // reliable.
+ String zoneId;
+
+ // Introduce bias towards the device's current zone when there are multiple zone suggested.
+ String deviceTimeZone = mCallback.getDeviceTimeZone();
+ if (zoneIds.contains(deviceTimeZone)) {
+ if (DBG) {
+ Slog.d(LOG_TAG,
+ "Geo tz suggestion contains current device time zone. Applying bias.");
+ }
+ zoneId = deviceTimeZone;
+ } else {
+ zoneId = zoneIds.get(0);
+ }
+ setDeviceTimeZoneIfRequired(zoneId, detectionReason);
+ }
+
+ /**
+ * Detects the time zone using the latest available telephony time zone suggestions.
+ * Finds the best available time zone suggestion from all slotIndexes. If it is high-enough
+ * quality and automatic time zone detection is enabled then it will be set on the device. The
+ * outcome can be that this strategy becomes / remains un-opinionated and nothing is set.
+ */
+ @GuardedBy("this")
+ private void doTelephonyTimeZoneDetection(@NonNull String detectionReason) {
QualifiedTelephonyTimeZoneSuggestion bestTelephonySuggestion =
findBestTelephonySuggestion();
@@ -468,9 +548,9 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
// slotIndex and find the best. Note that we deliberately do not look at age: the caller can
// rate-limit so age is not a strong indicator of confidence. Instead, the callers are
// expected to withdraw suggestions they no longer have confidence in.
- for (int i = 0; i < mSuggestionBySlotIndex.size(); i++) {
+ for (int i = 0; i < mTelephonySuggestionsBySlotIndex.size(); i++) {
QualifiedTelephonyTimeZoneSuggestion candidateSuggestion =
- mSuggestionBySlotIndex.valueAt(i);
+ mTelephonySuggestionsBySlotIndex.valueAt(i);
if (candidateSuggestion == null) {
// Unexpected
continue;
@@ -505,14 +585,10 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
@Override
public synchronized void handleAutoTimeZoneConfigChanged() {
if (DBG) {
- Slog.d(LOG_TAG, "handleTimeZoneDetectionChange() called");
- }
- if (mCallback.isAutoDetectionEnabled()) {
- // When the user enabled time zone detection, run the time zone detection and change the
- // device time zone if possible.
- String reason = "Auto time zone detection setting enabled.";
- doAutoTimeZoneDetection(reason);
+ Slog.d(LOG_TAG, "handleAutoTimeZoneConfigChanged()");
}
+
+ doAutoTimeZoneDetection("handleAutoTimeZoneConfigChanged()");
}
@Override
@@ -532,15 +608,21 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
ipw.println("mCallback.isDeviceTimeZoneInitialized()="
+ mCallback.isDeviceTimeZoneInitialized());
ipw.println("mCallback.getDeviceTimeZone()=" + mCallback.getDeviceTimeZone());
+ ipw.println("mCallback.isGeoDetectionEnabled()=" + mCallback.isGeoDetectionEnabled());
ipw.println("Time zone change log:");
ipw.increaseIndent(); // level 2
mTimeZoneChangesLog.dump(ipw);
ipw.decreaseIndent(); // level 2
+ ipw.println("Geolocation suggestion history:");
+ ipw.increaseIndent(); // level 2
+ mLatestGeoLocationSuggestion.dump(ipw);
+ ipw.decreaseIndent(); // level 2
+
ipw.println("Telephony suggestion history:");
ipw.increaseIndent(); // level 2
- mSuggestionBySlotIndex.dump(ipw);
+ mTelephonySuggestionsBySlotIndex.dump(ipw);
ipw.decreaseIndent(); // level 2
ipw.decreaseIndent(); // level 1
@@ -555,7 +637,15 @@ public final class TimeZoneDetectorStrategyImpl implements TimeZoneDetectorStrat
@VisibleForTesting
public synchronized QualifiedTelephonyTimeZoneSuggestion getLatestTelephonySuggestion(
int slotIndex) {
- return mSuggestionBySlotIndex.get(slotIndex);
+ return mTelephonySuggestionsBySlotIndex.get(slotIndex);
+ }
+
+ /**
+ * A method used to inspect strategy state during tests. Not intended for general use.
+ */
+ @VisibleForTesting
+ public GeolocationTimeZoneSuggestion getLatestGeolocationSuggestion() {
+ return mLatestGeoLocationSuggestion.get();
}
/**
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 2f695c6fd3f1..202a3dcf46dc 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -3070,7 +3070,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
mLockWallpaperMap.put(userId, wallpaper);
ensureSaneWallpaperData(wallpaper);
} else {
- // sanity fallback: we're in bad shape, but establishing a known
+ // rationality fallback: we're in bad shape, but establishing a known
// valid system+lock WallpaperData will keep us from dying.
Slog.wtf(TAG, "Didn't find wallpaper in non-lock case!");
wallpaper = new WallpaperData(userId, getWallpaperDir(userId),
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index e573d362fef4..e4f28546a5fd 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -107,6 +107,12 @@ import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
import static android.view.WindowManager.TRANSIT_UNSET;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.ActivityRecordProto.ALL_DRAWN;
@@ -172,12 +178,6 @@ import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchi
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
import static com.android.server.wm.Task.ActivityState.DESTROYED;
@@ -294,6 +294,7 @@ import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.ReferrerIntent;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.util.XmlUtils;
import com.android.internal.util.function.pooled.PooledConsumer;
@@ -305,7 +306,6 @@ import com.android.server.am.AppTimeTracker;
import com.android.server.am.PendingIntentRecord;
import com.android.server.display.color.ColorDisplayService;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.uri.NeededUriGrants;
import com.android.server.uri.UriPermissionOwner;
import com.android.server.wm.ActivityMetricsLogger.TransitionInfoSnapshot;
@@ -2549,7 +2549,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final Task stack = getRootTask();
final boolean mayAdjustTop = (isState(RESUMED) || stack.mResumedActivity == null)
- && stack.isFocusedStackOnDisplay();
+ && stack.isFocusedStackOnDisplay()
+ // Do not adjust focus task because the task will be reused to launch new activity.
+ && !task.isClearingToReuseTask();
final boolean shouldAdjustGlobalFocus = mayAdjustTop
// It must be checked before {@link #makeFinishingLocked} is called, because a stack
// is not visible if it only contains finishing activities.
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index f7cb0146ea52..15e88fc44746 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2023,8 +2023,6 @@ class ActivityStarter {
// of history or if it is finished immediately), thus disassociating the task. Also note
// that mReuseTask is reset as a result of {@link Task#performClearTaskLocked}
// launching another activity.
- // TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
- // already launching one.
targetTask.performClearTaskLocked();
targetTask.setIntent(mStartActivity);
mAddingToTask = true;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 31a9c5d4242c..403f225032e9 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -5347,15 +5347,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return mAmInternal.isBackgroundActivityStartsEnabled();
}
- void enableScreenAfterBoot(boolean booted) {
- writeBootProgressEnableScreen(SystemClock.uptimeMillis());
- mWindowManager.enableScreenAfterBoot();
-
- synchronized (mGlobalLock) {
- updateEventDispatchingLocked(booted);
- }
- }
-
static long getInputDispatchingTimeoutMillisLocked(ActivityRecord r) {
if (r == null || !r.hasProcess()) {
return DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
@@ -6449,9 +6440,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public void enableScreenAfterBoot(boolean booted) {
+ writeBootProgressEnableScreen(SystemClock.uptimeMillis());
+ mWindowManager.enableScreenAfterBoot();
synchronized (mGlobalLock) {
- writeBootProgressEnableScreen(SystemClock.uptimeMillis());
- mWindowManager.enableScreenAfterBoot();
updateEventDispatchingLocked(booted);
}
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 11a468be8f9f..f76108f332d1 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -67,10 +67,10 @@ import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpe
import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation;
import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
import static com.android.server.wm.AppTransitionProto.APP_TRANSITION_STATE;
import static com.android.server.wm.AppTransitionProto.LAST_USED_APP_TRANSITION;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -127,11 +127,11 @@ import android.view.animation.TranslateAnimation;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.DumpUtils.Dump;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.AttributeCache;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.animation.ClipRectLRAnimation;
import com.android.server.wm.animation.ClipRectTBAnimation;
import com.android.server.wm.animation.CurvedTranslateAnimation;
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 5720e9b7f193..57d51c51c12b 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -41,14 +41,14 @@ import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN;
import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SNAPSHOT;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SPLASH_SCREEN;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
import static com.android.server.wm.AppTransition.isKeyguardGoingAwayTransit;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
@@ -69,7 +69,7 @@ import android.view.WindowManager.TransitionType;
import android.view.animation.Animation;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import java.util.ArrayList;
import java.util.LinkedList;
diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java
index f563e57b363e..0b2c851c4366 100644
--- a/services/core/java/com/android/server/wm/BlackFrame.java
+++ b/services/core/java/com/android/server/wm/BlackFrame.java
@@ -16,13 +16,13 @@
package com.android.server.wm;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
import android.graphics.Rect;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import java.io.PrintWriter;
import java.util.function.Supplier;
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index 6ffb48282017..8bd42f03ff86 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -24,11 +24,11 @@ import static android.view.WindowManagerPolicyConstants.APPLICATION_LAYER;
import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOW_TOKENS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.internal.util.Preconditions.checkState;
import static com.android.server.wm.DisplayAreaProto.IS_TASK_DISPLAY_AREA;
import static com.android.server.wm.DisplayAreaProto.NAME;
import static com.android.server.wm.DisplayAreaProto.WINDOW_CONTAINER;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.WindowContainerChildProto.DISPLAY_AREA;
import android.annotation.Nullable;
@@ -38,8 +38,8 @@ import android.util.proto.ProtoOutputStream;
import android.window.DisplayAreaInfo;
import android.window.IDisplayAreaOrganizer;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import java.util.Comparator;
import java.util.function.BiFunction;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index fc170538994c..affbafa095cc 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -74,6 +74,14 @@ import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
@@ -94,14 +102,6 @@ import static com.android.server.wm.DisplayContentProto.ROOT_DISPLAY_AREA;
import static com.android.server.wm.DisplayContentProto.ROTATION;
import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
import static com.android.server.wm.DisplayContentProto.SINGLE_TASK_INSTANCE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_BOOT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.Task.ActivityState.RESUMED;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -203,6 +203,7 @@ import android.view.WindowManagerPolicyConstants.PointerEventListener;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.util.function.TriConsumer;
import com.android.internal.util.function.pooled.PooledConsumer;
@@ -211,7 +212,6 @@ import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.utils.DisplayRotationUtil;
import com.android.server.wm.utils.RotationCache;
import com.android.server.wm.utils.WmDisplayCutout;
@@ -1557,7 +1557,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
// the heavy operations. This also benefits that the states of multiple activities
// are handled together.
r.linkFixedRotationTransform(prevRotatedLaunchingApp);
- setFixedRotationLaunchingAppUnchecked(r, rotation);
+ if (r != mFixedRotationTransitionListener.mAnimatingRecents) {
+ // Only update the record for normal activity so the display orientation can be
+ // updated when the transition is done if it becomes the top. And the case of
+ // recents can be handled when the recents animation is finished.
+ setFixedRotationLaunchingAppUnchecked(r, rotation);
+ }
return;
}
@@ -4063,9 +4068,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM, "Taking screenshot while rotating");
// Send invalid rect and no width and height since it will screenshot the entire display.
- Rect frame = new Rect(0, 0, -1, -1);
- final Bitmap bitmap = SurfaceControl.screenshot(frame, 0, 0, inRotation,
- mDisplay.getRotation());
+ final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
+ final SurfaceControl.DisplayCaptureArgs captureArgs =
+ new SurfaceControl.DisplayCaptureArgs.Builder(displayToken)
+ .setUseIdentityTransform(inRotation)
+ .build();
+ final SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
+ SurfaceControl.captureDisplay(captureArgs);
+ final Bitmap bitmap = screenshotBuffer == null ? null : screenshotBuffer.asBitmap();
if (bitmap == null) {
Slog.w(TAG_WM, "Failed to take screenshot");
return null;
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 4f6f75d924c4..2e03cb80b189 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -112,6 +112,7 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
import static com.android.server.policy.PhoneWindowManager.TOAST_WINDOW_TIMEOUT;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER;
@@ -120,7 +121,6 @@ import static com.android.server.policy.WindowManagerPolicy.TRANSIT_HIDE;
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_SHOW;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -187,6 +187,7 @@ import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.GestureNavigationSettingsObserver;
import com.android.internal.policy.ScreenDecorationsUtils;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ScreenshotHelper;
import com.android.internal.util.function.TriConsumer;
import com.android.internal.view.AppearanceRegion;
@@ -199,7 +200,6 @@ import com.android.server.policy.WindowManagerPolicy.NavigationBarPosition;
import com.android.server.policy.WindowManagerPolicy.ScreenOnListener;
import com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs;
import com.android.server.policy.WindowOrientationListener;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wallpaper.WallpaperManagerInternal;
import com.android.server.wm.utils.InsetUtils;
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index c63128c15e8d..0206787ef226 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -22,8 +22,8 @@ import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -58,12 +58,12 @@ import android.window.WindowContainerTransaction;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.UiThread;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.policy.WindowOrientationListener;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.statusbar.StatusBarManagerInternal;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 22dd1d332345..133b11116460 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -18,11 +18,11 @@ package com.android.server.wm;
import static android.os.IInputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.DragDropController.MSG_ANIMATION_END;
import static com.android.server.wm.DragDropController.MSG_DRAG_END_TIMEOUT;
import static com.android.server.wm.DragDropController.MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -58,9 +58,9 @@ import android.view.WindowManager;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.view.IDragAndDropPermissions;
import com.android.server.LocalServices;
-import com.android.server.protolog.common.ProtoLog;
import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index e7fbc334306e..86e2698302aa 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -16,13 +16,13 @@
package com.android.server.wm;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
import android.view.InsetsSource;
import android.view.WindowInsets;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 791f47128be0..0fe9735c9e46 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -41,7 +41,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -60,8 +60,8 @@ import android.view.InputEventReceiver;
import android.view.InputWindowHandle;
import android.view.SurfaceControl;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import java.io.PrintWriter;
import java.util.Set;
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index f64149cee8c7..d1eb79556d1d 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -24,7 +24,7 @@ import static android.view.ViewRootImpl.NEW_INSETS_MODE_IME;
import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.ViewRootImpl.sNewInsetsMode;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_INSETS_CONTROL;
import static com.android.server.wm.WindowManagerService.H.LAYOUT_AND_ASSIGN_WINDOW_LAYERS_IF_NEEDED;
@@ -40,8 +40,8 @@ import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.function.TriConsumer;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 9c978fd0c867..ab1074ee2821 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -30,7 +30,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -45,8 +45,8 @@ import android.view.InsetsState;
import android.view.InsetsState.InternalInsetsType;
import android.view.WindowManager;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.inputmethod.InputMethodManagerInternal;
-import com.android.server.protolog.common.ProtoLog;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -105,6 +105,10 @@ class InsetsStateController {
* @return The state stripped of the necessary information.
*/
InsetsState getInsetsForDispatch(@NonNull WindowState target) {
+ final InsetsState rotatedState = target.mToken.getFixedRotationTransformInsetsState();
+ if (rotatedState != null) {
+ return rotatedState;
+ }
final InsetsSourceProvider provider = target.getControllableInsetProvider();
final @InternalInsetsType int type = provider != null
? provider.getSource().getType() : ITYPE_INVALID;
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index df5356303f8b..3c64ffb237d6 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -1627,8 +1627,8 @@ class RecentTasks {
}
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: adding affilliates starting at "
+ topIndex + " from intial " + taskIndex);
- // Find the end of the chain, doing a sanity check along the way.
- boolean sane = top.mAffiliatedTaskId == task.mAffiliatedTaskId;
+ // Find the end of the chain, doing a validity check along the way.
+ boolean isValid = top.mAffiliatedTaskId == task.mAffiliatedTaskId;
int endIndex = topIndex;
Task prev = top;
while (endIndex < recentsCount) {
@@ -1640,7 +1640,7 @@ class RecentTasks {
if (cur.mNextAffiliate != null || cur.mNextAffiliateTaskId != INVALID_TASK_ID) {
Slog.wtf(TAG, "Bad chain @" + endIndex
+ ": first task has next affiliate: " + prev);
- sane = false;
+ isValid = false;
break;
}
} else {
@@ -1652,7 +1652,7 @@ class RecentTasks {
+ " has bad next affiliate "
+ cur.mNextAffiliate + " id " + cur.mNextAffiliateTaskId
+ ", expected " + prev);
- sane = false;
+ isValid = false;
break;
}
}
@@ -1662,7 +1662,7 @@ class RecentTasks {
Slog.wtf(TAG, "Bad chain @" + endIndex
+ ": last task " + cur + " has previous affiliate "
+ cur.mPrevAffiliate);
- sane = false;
+ isValid = false;
}
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: end of chain @" + endIndex);
break;
@@ -1673,7 +1673,7 @@ class RecentTasks {
+ ": task " + cur + " has previous affiliate "
+ cur.mPrevAffiliate + " but should be id "
+ cur.mPrevAffiliate);
- sane = false;
+ isValid = false;
break;
}
}
@@ -1682,7 +1682,7 @@ class RecentTasks {
+ ": task " + cur + " has affiliated id "
+ cur.mAffiliatedTaskId + " but should be "
+ task.mAffiliatedTaskId);
- sane = false;
+ isValid = false;
break;
}
prev = cur;
@@ -1690,18 +1690,18 @@ class RecentTasks {
if (endIndex >= recentsCount) {
Slog.wtf(TAG, "Bad chain ran off index " + endIndex
+ ": last task " + prev);
- sane = false;
+ isValid = false;
break;
}
}
- if (sane) {
+ if (isValid) {
if (endIndex < taskIndex) {
Slog.wtf(TAG, "Bad chain @" + endIndex
+ ": did not extend to task " + task + " @" + taskIndex);
- sane = false;
+ isValid = false;
}
}
- if (sane) {
+ if (isValid) {
// All looks good, we can just move all of the affiliated tasks
// to the top.
for (int i=topIndex; i<=endIndex; i++) {
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index d7b43bc5537d..6c416830b59e 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -25,8 +25,8 @@ import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.WindowManager.TRANSIT_NONE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_TOP;
@@ -41,9 +41,9 @@ import android.os.Trace;
import android.util.Slog;
import android.view.IRecentsAnimationRunner;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.ActivityMetricsLogger.LaunchingState;
import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 6b3a5d6bf18c..143fbb0fe48b 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -23,10 +23,10 @@ import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM;
import static com.android.server.wm.AnimationAdapterProto.REMOTE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.WindowManagerInternal.AppTransitionListener;
@@ -56,12 +56,12 @@ import android.view.SurfaceControl.Transaction;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.inputmethod.SoftInputShowHideReason;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledFunction;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.inputmethod.InputMethodManagerInternal;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index c255a18190f7..e7461e7d5517 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -16,8 +16,8 @@
package com.android.server.wm;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS;
import static com.android.server.wm.AnimationAdapterProto.REMOTE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS;
import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -37,9 +37,9 @@ import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
+import com.android.internal.protolog.ProtoLogImpl;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.FastPrintWriter;
-import com.android.server.protolog.ProtoLogImpl;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 1cb483c1d1a0..fe2d08f6a4c2 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -41,6 +41,11 @@ import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY;
import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.policy.PhoneWindowManager.SYSTEM_DIALOG_REASON_ASSIST;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
@@ -59,11 +64,6 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATE
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
import static com.android.server.wm.ActivityTaskManagerService.TAG_SWITCH;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
import static com.android.server.wm.RootWindowContainerProto.IS_HOME_RECENTS_COMPONENT;
import static com.android.server.wm.RootWindowContainerProto.KEYGUARD_CONTROLLER;
@@ -146,6 +146,7 @@ import android.window.WindowContainerToken;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledFunction;
import com.android.internal.util.function.pooled.PooledLambda;
@@ -155,7 +156,6 @@ import com.android.server.am.ActivityManagerService;
import com.android.server.am.AppTimeTracker;
import com.android.server.am.UserState;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -737,7 +737,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
winAnimator.mSession.mPid, operation);
final long callingIdentity = Binder.clearCallingIdentity();
try {
- // There was some problem...first, do a sanity check of the window list to make sure
+ // There was some problem...first, do a validity check of the window list to make sure
// we haven't left any dangling surfaces around.
Slog.i(TAG_WM, "Out of memory for surface! Looking for leaks...");
@@ -811,7 +811,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
// "Something has changed! Let's make it correct now."
- // TODO: Super crazy long method that should be broken down...
+ // TODO: Super long method that should be broken down...
void performSurfacePlacementNoTrace() {
if (DEBUG_WINDOW_TRACE) Slog.v(TAG, "performSurfacePlacementInner: entry. Called by "
+ Debug.getCallers(3));
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index d7b8fb00d05c..3c8036d4e3b6 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -18,9 +18,9 @@ package com.android.server.wm;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
import static com.android.server.wm.AnimationSpecProto.ROTATE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
import static com.android.server.wm.RotationAnimationSpecProto.DURATION_MS;
import static com.android.server.wm.RotationAnimationSpecProto.END_LUMA;
import static com.android.server.wm.RotationAnimationSpecProto.START_LUMA;
@@ -50,7 +50,7 @@ import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;
import com.android.internal.R;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
import com.android.server.wm.utils.RotationAnimationUtils;
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 86cbf3e3afe1..3b32a9d76258 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -24,7 +24,7 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -58,7 +58,7 @@ import android.view.SurfaceSession;
import android.view.WindowManager;
import com.android.internal.os.logging.MetricsLoggerWrapper;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.wm.WindowManagerService.H;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/SurfaceFreezer.java b/services/core/java/com/android/server/wm/SurfaceFreezer.java
index 1c9743041923..d9365c5d0666 100644
--- a/services/core/java/com/android/server/wm/SurfaceFreezer.java
+++ b/services/core/java/com/android/server/wm/SurfaceFreezer.java
@@ -16,7 +16,7 @@
package com.android.server.wm;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_SCREEN_ROTATION;
@@ -28,7 +28,7 @@ import android.hardware.HardwareBuffer;
import android.view.Surface;
import android.view.SurfaceControl;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import java.util.function.Supplier;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index be0815b06051..0529abf89f6e 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -78,6 +78,8 @@ import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP;
import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
@@ -116,8 +118,6 @@ import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.server.wm.Task.ActivityState.PAUSED;
import static com.android.server.wm.Task.ActivityState.PAUSING;
import static com.android.server.wm.Task.ActivityState.RESUMED;
@@ -210,6 +210,7 @@ import android.window.ITaskOrganizer;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.XmlUtils;
import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledFunction;
@@ -218,7 +219,6 @@ import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService;
import com.android.server.am.AppTimeTracker;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.uri.NeededUriGrants;
import org.xmlpull.v1.XmlPullParser;
@@ -1836,14 +1836,25 @@ class Task extends WindowContainer<WindowContainer> {
*/
void performClearTaskLocked() {
mReuseTask = true;
- performClearTask("clear-task-all");
- mReuseTask = false;
+ mStackSupervisor.beginDeferResume();
+ try {
+ performClearTask("clear-task-all");
+ } finally {
+ mStackSupervisor.endDeferResume();
+ mReuseTask = false;
+ }
}
ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
mReuseTask = true;
- final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
- mReuseTask = false;
+ mStackSupervisor.beginDeferResume();
+ final ActivityRecord result;
+ try {
+ result = performClearTaskLocked(newR, launchFlags);
+ } finally {
+ mStackSupervisor.endDeferResume();
+ mReuseTask = false;
+ }
return result;
}
@@ -7056,17 +7067,21 @@ class Task extends WindowContainer<WindowContainer> {
/**
* Reset local parameters because an app's activity died.
* @param app The app of the activity that died.
+ * @return {@code true} if the process of the pausing activity is died.
*/
- void handleAppDied(WindowProcessController app) {
+ boolean handleAppDied(WindowProcessController app) {
+ boolean isPausingDied = false;
if (mPausingActivity != null && mPausingActivity.app == app) {
if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE,
"App died while pausing: " + mPausingActivity);
mPausingActivity = null;
+ isPausingDied = true;
}
if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
+ return isPausingDied;
}
boolean dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index a847744247c7..32511108836e 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -32,13 +32,13 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.wm.ActivityTaskManagerService.TAG_STACK;
import static com.android.server.wm.DisplayContent.alwaysCreateStack;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.RootWindowContainer.TAG_STATES;
import static com.android.server.wm.Task.ActivityState.RESUMED;
import static com.android.server.wm.Task.STACK_VISIBILITY_VISIBLE;
@@ -58,10 +58,10 @@ import android.view.SurfaceControl;
import android.window.WindowContainerTransaction;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
-import com.android.server.protolog.common.ProtoLog;
import java.io.PrintWriter;
import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 3fbc0373e1a9..a66cd846e8be 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -26,8 +26,8 @@ import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_LEFT;
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_NONE;
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_RIGHT;
import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_TOP;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -59,7 +59,7 @@ import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.TaskResizingAlgorithm;
import com.android.internal.policy.TaskResizingAlgorithm.CtrlType;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
class TaskPositioner implements IBinder.DeathRecipient {
private static final boolean DEBUG_ORIENTATION_VIOLATIONS = false;
diff --git a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
index 1103bf19b3bf..3def0911bd76 100644
--- a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
+++ b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
@@ -15,14 +15,14 @@
*/
package com.android.server.wm;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import android.hardware.HardwareBuffer;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import java.util.function.Function;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 68445f6970fb..dbbb7ff69b3b 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -27,7 +27,6 @@ import android.annotation.Nullable;
import android.app.ActivityManager.TaskSnapshot;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
-import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.RecordingCanvas;
@@ -82,7 +81,7 @@ class TaskSnapshotController {
/**
* Return value for {@link #getSnapshotMode}: We are not allowed to take a real screenshot but
- * we should try to use the app theme to create a dummy representation of the app.
+ * we should try to use the app theme to create a fake representation of the app.
*/
@VisibleForTesting
static final int SNAPSHOT_MODE_APP_THEME = 1;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 9b18ac8f7702..e9ada6be7e7b 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -41,7 +41,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
import static com.android.internal.policy.DecorView.getNavigationBarRect;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
import static com.android.server.wm.TaskSnapshotController.getSystemBarInsets;
import static com.android.server.wm.TaskSnapshotController.mergeInsetsSources;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -83,9 +83,9 @@ import android.view.WindowManagerGlobal;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.DecorView;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.view.BaseIWindow;
import com.android.server.policy.WindowManagerPolicy.StartingSurface;
-import com.android.server.protolog.common.ProtoLog;
/**
* This class represents a starting window that shows a snapshot.
diff --git a/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java b/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java
index f46701536cf8..38bff9ed3c31 100644
--- a/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java
@@ -15,8 +15,8 @@
*/
package com.android.server.wm;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS;
import static com.android.server.wm.AnimationAdapterProto.REMOTE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS;
import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
@@ -26,7 +26,7 @@ import android.util.proto.ProtoOutputStream;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.wm.SurfaceAnimator.AnimationType;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 6377a2169b34..5c6266a2f8c4 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -16,7 +16,7 @@
package com.android.server.wm;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
@@ -36,8 +36,8 @@ import android.util.TimeUtils;
import android.view.Choreographer;
import android.view.SurfaceControl;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import java.io.PrintWriter;
import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index e24d185557e8..8a5e70f2e353 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -28,14 +28,14 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.os.UserHandle.USER_NULL;
import static android.view.SurfaceControl.Transaction;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.AppTransition.MAX_APP_TRANSITION_DURATION;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
@@ -82,8 +82,8 @@ import android.window.IWindowContainerToken;
import android.window.WindowContainerToken;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.ToBooleanFunction;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.SurfaceAnimator.Animatable;
import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
diff --git a/services/core/java/com/android/server/wm/WindowContainerThumbnail.java b/services/core/java/com/android/server/wm/WindowContainerThumbnail.java
index b75f886520e6..b9f67a590c2a 100644
--- a/services/core/java/com/android/server/wm/WindowContainerThumbnail.java
+++ b/services/core/java/com/android/server/wm/WindowContainerThumbnail.java
@@ -19,7 +19,7 @@ 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.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.WindowContainerThumbnailProto.HEIGHT;
import static com.android.server.wm.WindowContainerThumbnailProto.SURFACE_ANIMATOR;
@@ -39,7 +39,7 @@ import android.view.SurfaceControl.Builder;
import android.view.SurfaceControl.Transaction;
import android.view.animation.Animation;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.wm.SurfaceAnimator.Animatable;
import com.android.server.wm.SurfaceAnimator.AnimationType;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0b1d6bc0adfd..7624d4c1ea36 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -84,22 +84,22 @@ import static android.view.WindowManagerGlobal.RELAYOUT_RES_BLAST_SYNC;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_ERROR;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN;
import static com.android.server.LockGuard.INDEX_WINDOW;
import static com.android.server.LockGuard.installLock;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_BOOT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
-import static com.android.server.wm.ProtoLogGroup.WM_ERROR;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -265,6 +265,8 @@ import com.android.internal.os.IResultReceiver;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
import com.android.internal.policy.KeyInterceptionInfo;
+import com.android.internal.protolog.ProtoLogImpl;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.LatencyTracker;
@@ -281,8 +283,6 @@ import com.android.server.input.InputManagerService;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.policy.WindowManagerPolicy.ScreenOffListener;
import com.android.server.power.ShutdownThread;
-import com.android.server.protolog.ProtoLogImpl;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.utils.PriorityDump;
import com.android.server.wm.utils.DeviceConfigInterface;
@@ -3612,7 +3612,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (SHOW_VERBOSE_TRANSACTIONS) Slog.i(TAG_WM, ">>> showStrictModeViolation");
- // TODO: Modify this to use the surface trace once it is not going crazy.
+ // TODO: Modify this to use the surface trace once it is not going baffling.
// b/31532461
// TODO(multi-display): support multiple displays
if (mStrictModeFlash == null) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index bdecb8d99752..271d2b1a002f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -31,7 +31,7 @@ import android.view.Surface;
import android.view.ViewDebug;
import com.android.internal.os.ByteTransferPipe;
-import com.android.server.protolog.ProtoLogImpl;
+import com.android.internal.protolog.ProtoLogImpl;
import java.io.IOException;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 70c30c9180d7..c714eeb92e68 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -196,7 +196,6 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
private final Configuration mLastReportedConfiguration = new Configuration();
// Configuration that is waiting to be dispatched to the process.
private Configuration mPendingConfiguration;
- private final Configuration mNewOverrideConfig = new Configuration();
// Registered display id as a listener to override config change
private int mDisplayId;
private ActivityRecord mConfigActivityRecord;
@@ -1201,7 +1200,10 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
final Task rootTask = r.getRootTask();
if (rootTask != null) {
- rootTask.handleAppDied(this);
+ // There may be a pausing activity that hasn't shown any window and was requested
+ // to be hidden. But pausing is also a visible state, it should be regarded as
+ // visible, so the caller can know the next activity should be resumed.
+ hasVisibleActivities |= rootTask.handleAppDied(this);
}
r.handleAppDied();
}
@@ -1289,11 +1291,26 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
}
@Override
+ public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
+ super.onRequestedOverrideConfigurationChanged(
+ sanitizeProcessConfiguration(overrideConfiguration));
+ }
+
+ @Override
public void onMergedOverrideConfigurationChanged(Configuration mergedOverrideConfig) {
+ super.onRequestedOverrideConfigurationChanged(
+ sanitizeProcessConfiguration(mergedOverrideConfig));
+ }
+
+ private static Configuration sanitizeProcessConfiguration(Configuration config) {
// Make sure that we don't accidentally override the activity type.
- mNewOverrideConfig.setTo(mergedOverrideConfig);
- mNewOverrideConfig.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
- super.onRequestedOverrideConfigurationChanged(mNewOverrideConfig);
+ if (config.windowConfiguration.getActivityType() != ACTIVITY_TYPE_UNDEFINED) {
+ final Configuration sanitizedConfig = new Configuration(config);
+ sanitizedConfig.windowConfiguration.setActivityType(ACTIVITY_TYPE_UNDEFINED);
+ return sanitizedConfig;
+ }
+
+ return config;
}
private void updateConfiguration() {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index ab78e74b9e37..49e623d8dd11 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -101,6 +101,14 @@ import static android.view.WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFO
import static android.view.WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RESIZE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
import static com.android.server.am.ActivityManagerService.MY_PID;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER;
@@ -116,14 +124,6 @@ import static com.android.server.wm.IdentifierProto.USER_ID;
import static com.android.server.wm.MoveAnimationSpecProto.DURATION_MS;
import static com.android.server.wm.MoveAnimationSpecProto.FROM;
import static com.android.server.wm.MoveAnimationSpecProto.TO;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_IME;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RESIZE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -236,10 +236,10 @@ import android.view.animation.Interpolator;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.KeyInterceptionInfo;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.ToBooleanFunction;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.utils.WmDisplayCutout;
@@ -1535,10 +1535,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
InsetsState getInsetsState() {
- final InsetsState insetsState = mToken.getFixedRotationTransformInsetsState();
- if (insetsState != null) {
- return insetsState;
- }
return getDisplayContent().getInsetsPolicy().getInsetsForDispatch(this);
}
@@ -2460,9 +2456,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
finishInputEvent(event, true);
}
}
- /**
- * Dummy event receiver for windows that died visible.
- */
+ /** Fake event receiver for windows that died visible. */
private DeadWindowEventReceiver mDeadWindowEventReceiver;
void openInputChannel(InputChannel outInputChannel) {
@@ -2480,9 +2474,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mClientChannel.dispose();
mClientChannel = null;
} else {
- // If the window died visible, we setup a dummy input channel, so that taps
+ // If the window died visible, we setup a fake input channel, so that taps
// can still detected by input monitor channel, and we can relaunch the app.
- // Create dummy event receiver that simply reports all events as handled.
+ // Create fake event receiver that simply reports all events as handled.
mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
}
mWmService.mInputToWindowMap.put(mInputWindowHandle.token, this);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index d0101adaabad..92177abbbf85 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -31,13 +31,13 @@ import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.TRANSIT_NONE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_DRAW;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_DRAW;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
@@ -76,8 +76,8 @@ import android.view.WindowManager.LayoutParams;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import java.io.PrintWriter;
@@ -560,9 +560,9 @@ class WindowStateAnimator {
}
}
- // Something is wrong and SurfaceFlinger will not like this, try to revert to sane values.
- // This doesn't necessarily mean that there is an error in the system. The sizes might be
- // incorrect, because it is before the first layout or draw.
+ // Something is wrong and SurfaceFlinger will not like this, try to revert to reasonable
+ // values. This doesn't necessarily mean that there is an error in the system. The sizes
+ // might be incorrect, because it is before the first layout or draw.
if (outSize.width() < 1) {
outSize.right = 1;
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index b89cdd32e132..9b40822c8ab5 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -21,8 +21,8 @@ import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW;
import static android.view.SurfaceControl.METADATA_OWNER_UID;
import static android.view.SurfaceControl.METADATA_WINDOW_TYPE;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
-import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
+import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -40,7 +40,7 @@ import android.view.SurfaceControl;
import android.view.WindowContentFrameStats;
import android.view.WindowManager;
-import com.android.server.protolog.common.ProtoLog;
+import com.android.internal.protolog.common.ProtoLog;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 2c1bb3ec51eb..bc4d9a973ecb 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -23,10 +23,10 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
-import static com.android.server.wm.ProtoLogGroup.WM_ERROR;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
+import static com.android.internal.protolog.ProtoLogGroup.WM_ERROR;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -59,8 +59,8 @@ import android.view.SurfaceControl;
import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.protolog.common.ProtoLog;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -548,7 +548,7 @@ class WindowToken extends WindowContainer<WindowState> {
void applyFixedRotationTransform(DisplayInfo info, DisplayFrames displayFrames,
Configuration config) {
if (mFixedRotationTransformState != null) {
- return;
+ cleanUpFixedRotationTransformState(true /* replacing */);
}
mFixedRotationTransformState = new FixedRotationTransformState(info, displayFrames,
new Configuration(config), mDisplayContent.getRotation());
@@ -565,13 +565,13 @@ class WindowToken extends WindowContainer<WindowState> {
* one. This takes the same effect as {@link #applyFixedRotationTransform}.
*/
void linkFixedRotationTransform(WindowToken other) {
- if (mFixedRotationTransformState != null) {
- return;
- }
final FixedRotationTransformState fixedRotationState = other.mFixedRotationTransformState;
- if (fixedRotationState == null) {
+ if (fixedRotationState == null || mFixedRotationTransformState == fixedRotationState) {
return;
}
+ if (mFixedRotationTransformState != null) {
+ cleanUpFixedRotationTransformState(true /* replacing */);
+ }
mFixedRotationTransformState = fixedRotationState;
fixedRotationState.mAssociatedTokens.add(this);
onConfigurationChanged(getParent().getConfiguration());
@@ -626,11 +626,17 @@ class WindowToken extends WindowContainer<WindowState> {
// The state is cleared at the end, because it is used to indicate that other windows can
// use seamless rotation when applying rotation to display.
for (int i = state.mAssociatedTokens.size() - 1; i >= 0; i--) {
- state.mAssociatedTokens.get(i).cleanUpFixedRotationTransformState();
+ state.mAssociatedTokens.get(i).cleanUpFixedRotationTransformState(
+ false /* replacing */);
}
}
- private void cleanUpFixedRotationTransformState() {
+ private void cleanUpFixedRotationTransformState(boolean replacing) {
+ if (replacing && mFixedRotationTransformState.mAssociatedTokens.size() > 1) {
+ // The state is not only used by self. Make sure to leave the influence by others.
+ mFixedRotationTransformState.mAssociatedTokens.remove(this);
+ mFixedRotationTransformState.mRotatedContainers.remove(this);
+ }
mFixedRotationTransformState = null;
notifyFixedRotationTransform(false /* enabled */);
}
diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java
index ba3dc607f6cc..e8b8bfce21a3 100644
--- a/services/core/java/com/android/server/wm/WindowTracing.java
+++ b/services/core/java/com/android/server/wm/WindowTracing.java
@@ -34,7 +34,7 @@ import android.util.Log;
import android.util.proto.ProtoOutputStream;
import android.view.Choreographer;
-import com.android.server.protolog.ProtoLogImpl;
+import com.android.internal.protolog.ProtoLogImpl;
import com.android.internal.util.TraceBuffer;
import java.io.File;
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index b6633ced771b..529fb8838aa1 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -17,9 +17,7 @@
#define LOG_TAG "VibratorService"
#include <android/hardware/vibrator/1.3/IVibrator.h>
-#include <android/hardware/vibrator/BnVibratorCallback.h>
#include <android/hardware/vibrator/IVibrator.h>
-#include <binder/IServiceManager.h>
#include "jni.h"
#include <nativehelper/JNIHelp.h>
@@ -28,19 +26,11 @@
#include <utils/misc.h>
#include <utils/Log.h>
-#include <hardware/vibrator.h>
#include <inttypes.h>
-#include <stdio.h>
#include <vibratorservice/VibratorHalController.h>
-using android::hardware::Return;
-using android::hardware::Void;
-using android::hardware::vibrator::V1_0::EffectStrength;
-using android::hardware::vibrator::V1_0::Status;
-using android::hardware::vibrator::V1_1::Effect_1_1;
-
namespace V1_0 = android::hardware::vibrator::V1_0;
namespace V1_1 = android::hardware::vibrator::V1_1;
namespace V1_2 = android::hardware::vibrator::V1_2;
@@ -87,150 +77,7 @@ static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) ==
static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) ==
static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK));
-class VibratorCallback {
- public:
- VibratorCallback(JNIEnv *env, jobject vibration) :
- mVibration(MakeGlobalRefOrDie(env, vibration)) {}
-
- ~VibratorCallback() {
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- env->DeleteGlobalRef(mVibration);
- }
-
- void onComplete() {
- auto env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(mVibration, sMethodIdOnComplete);
- }
-
- private:
- jobject mVibration;
-};
-
-class AidlVibratorCallback : public aidl::BnVibratorCallback {
- public:
- AidlVibratorCallback(JNIEnv *env, jobject vibration) :
- mCb(env, vibration) {}
-
- binder::Status onComplete() override {
- mCb.onComplete();
- return binder::Status::ok(); // oneway, local call
- }
-
- private:
- VibratorCallback mCb;
-};
-
-static constexpr int NUM_TRIES = 2;
-
-template<class R>
-inline R NoneStatus() {
- using ::android::hardware::Status;
- return Status::fromExceptionCode(Status::EX_NONE);
-}
-
-template<>
-inline binder::Status NoneStatus() {
- using binder::Status;
- return Status::fromExceptionCode(Status::EX_NONE);
-}
-
-// Creates a Return<R> with STATUS::EX_NULL_POINTER.
-template<class R>
-inline R NullptrStatus() {
- using ::android::hardware::Status;
- return Status::fromExceptionCode(Status::EX_NULL_POINTER);
-}
-
-template<>
-inline binder::Status NullptrStatus() {
- using binder::Status;
- return Status::fromExceptionCode(Status::EX_NULL_POINTER);
-}
-
-template <typename I>
-sp<I> getService() {
- return I::getService();
-}
-
-template <>
-sp<aidl::IVibrator> getService() {
- return waitForVintfService<aidl::IVibrator>();
-}
-
-template <typename I>
-sp<I> tryGetService() {
- return I::tryGetService();
-}
-
-template <>
-sp<aidl::IVibrator> tryGetService() {
- return checkVintfService<aidl::IVibrator>();
-}
-
-template <typename I>
-class HalWrapper {
- public:
- static std::unique_ptr<HalWrapper> Create() {
- // Assume that if getService returns a nullptr, HAL is not available on the
- // device.
- auto hal = getService<I>();
- return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr;
- }
-
- // Helper used to transparently deal with the vibrator HAL becoming unavailable.
- template<class R, class... Args0, class... Args1>
- R call(R (I::* fn)(Args0...), Args1&&... args1) {
- // Return<R> doesn't have a default constructor, so make a Return<R> with
- // STATUS::EX_NONE.
- R ret{NoneStatus<R>()};
-
- // Note that ret is guaranteed to be changed after this loop.
- for (int i = 0; i < NUM_TRIES; ++i) {
- ret = (mHal == nullptr) ? NullptrStatus<R>()
- : (*mHal.*fn)(std::forward<Args1>(args1)...);
-
- if (ret.isOk()) {
- break;
- }
-
- ALOGE("Failed to issue command to vibrator HAL. Retrying.");
-
- // Restoring connection to the HAL.
- mHal = tryGetService<I>();
- }
- return ret;
- }
-
- private:
- HalWrapper(sp<I> &&hal) : mHal(std::move(hal)) {}
-
- private:
- sp<I> mHal;
-};
-
-template <typename I>
-static auto getHal() {
- static auto sHalWrapper = HalWrapper<I>::Create();
- return sHalWrapper.get();
-}
-
-template<class R, class I, class... Args0, class... Args1>
-R halCall(R (I::* fn)(Args0...), Args1&&... args1) {
- auto hal = getHal<I>();
- return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>();
-}
-
-template<class R>
-bool isValidEffect(jlong effect) {
- if (effect < 0) {
- return false;
- }
- R val = static_cast<R>(effect);
- auto iter = hardware::hidl_enum_range<R>();
- return val >= *iter.begin() && val <= *std::prev(iter.end());
-}
-
-static void callVibrationOnComplete(jobject vibration) {
+static inline void callVibrationOnComplete(jobject vibration) {
if (vibration == nullptr) {
return;
}
@@ -257,14 +104,6 @@ static void destroyVibratorController(void* rawVibratorController) {
}
static jlong vibratorInit(JNIEnv* /* env */, jclass /* clazz */) {
- if (auto hal = getHal<aidl::IVibrator>()) {
- // IBinder::pingBinder isn't accessible as a pointer function
- // but getCapabilities can serve the same purpose
- int32_t cap;
- hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk();
- } else {
- halCall(&V1_0::IVibrator::ping).isOk();
- }
std::unique_ptr<vibrator::HalController> controller =
std::make_unique<vibrator::HalController>();
controller->init();
@@ -342,70 +181,19 @@ static jintArray vibratorGetSupportedEffects(JNIEnv* env, jclass /* clazz */, jl
return effects;
}
-static jlong vibratorPerformEffect(JNIEnv* env, jclass /* clazz */, jlong effect, jlong strength,
- jobject vibration, jboolean withCallback) {
- if (auto hal = getHal<aidl::IVibrator>()) {
- int32_t lengthMs;
- sp<AidlVibratorCallback> effectCallback =
- (withCallback != JNI_FALSE ? new AidlVibratorCallback(env, vibration) : nullptr);
- aidl::Effect effectType(static_cast<aidl::Effect>(effect));
- aidl::EffectStrength effectStrength(static_cast<aidl::EffectStrength>(strength));
-
- auto status = hal->call(&aidl::IVibrator::perform, effectType, effectStrength, effectCallback, &lengthMs);
- if (!status.isOk()) {
- if (status.exceptionCode() != binder::Status::EX_UNSUPPORTED_OPERATION) {
- ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32
- ": %s", static_cast<int64_t>(effect), static_cast<int32_t>(strength), status.toString8().string());
- }
- return -1;
- }
- return lengthMs;
- } else {
- Status status;
- uint32_t lengthMs;
- auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) {
- status = retStatus;
- lengthMs = retLengthMs;
- };
- EffectStrength effectStrength(static_cast<EffectStrength>(strength));
-
- Return<void> ret;
- if (isValidEffect<V1_0::Effect>(effect)) {
- ret = halCall(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(effect),
- effectStrength, callback);
- } else if (isValidEffect<Effect_1_1>(effect)) {
- ret = halCall(&V1_1::IVibrator::perform_1_1, static_cast<Effect_1_1>(effect),
- effectStrength, callback);
- } else if (isValidEffect<V1_2::Effect>(effect)) {
- ret = halCall(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(effect),
- effectStrength, callback);
- } else if (isValidEffect<V1_3::Effect>(effect)) {
- ret = halCall(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(effect),
- effectStrength, callback);
- } else {
- ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")",
- static_cast<int32_t>(effect));
- return -1;
- }
-
- if (!ret.isOk()) {
- ALOGW("Failed to perform effect (%" PRId32 ")", static_cast<int32_t>(effect));
- return -1;
- }
-
- if (status == Status::OK) {
- return lengthMs;
- } else if (status != Status::UNSUPPORTED_OPERATION) {
- // Don't warn on UNSUPPORTED_OPERATION, that's a normal event and just means the motor
- // doesn't have a pre-defined waveform to perform for it, so we should just give the
- // opportunity to fall back to the framework waveforms.
- ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32
- ", error=%" PRIu32 ").", static_cast<int64_t>(effect),
- static_cast<int32_t>(strength), static_cast<uint32_t>(status));
- }
+static jlong vibratorPerformEffect(JNIEnv* env, jclass /* clazz */, jlong controllerPtr,
+ jlong effect, jlong strength, jobject vibration) {
+ vibrator::HalController* controller = reinterpret_cast<vibrator::HalController*>(controllerPtr);
+ if (controller == nullptr) {
+ ALOGE("vibratorPerformEffect failed because controller was not initialized");
+ return -1;
}
-
- return -1;
+ aidl::Effect effectType = static_cast<aidl::Effect>(effect);
+ aidl::EffectStrength effectStrength = static_cast<aidl::EffectStrength>(strength);
+ jobject vibrationRef = vibration == nullptr ? vibration : MakeGlobalRefOrDie(env, vibration);
+ auto callback = [vibrationRef]() { callVibrationOnComplete(vibrationRef); };
+ auto result = controller->performEffect(effectType, effectStrength, callback);
+ return result.isOk() ? result.value().count() : -1;
}
static void vibratorPerformComposedEffect(JNIEnv* env, jclass /* clazz */, jlong controllerPtr,
@@ -464,7 +252,7 @@ static const JNINativeMethod method_table[] = {
{"vibratorOn", "(JJLcom/android/server/VibratorService$Vibration;)V", (void*)vibratorOn},
{"vibratorOff", "(J)V", (void*)vibratorOff},
{"vibratorSetAmplitude", "(JI)V", (void*)vibratorSetAmplitude},
- {"vibratorPerformEffect", "(JJLcom/android/server/VibratorService$Vibration;Z)J",
+ {"vibratorPerformEffect", "(JJJLcom/android/server/VibratorService$Vibration;)J",
(void*)vibratorPerformEffect},
{"vibratorPerformComposedEffect",
"(J[Landroid/os/VibrationEffect$Composition$PrimitiveEffect;Lcom/android/server/"
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
new file mode 100644
index 000000000000..6fea2aaf728b
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -0,0 +1,1116 @@
+/*
+ * Copyright (C) 2020 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.devicepolicy;
+
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+
+import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.END_TAG;
+import static org.xmlpull.v1.XmlPullParser.TEXT;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.admin.DeviceAdminInfo;
+import android.app.admin.DevicePolicyManager;
+import android.app.admin.FactoryResetProtectionPolicy;
+import android.app.admin.PasswordPolicy;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.PersistableBundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.Slog;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
+import com.android.internal.util.XmlUtils;
+import com.android.server.pm.UserRestrictionsUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+
+class ActiveAdmin {
+ private static final String TAG_DISABLE_KEYGUARD_FEATURES = "disable-keyguard-features";
+ private static final String TAG_TEST_ONLY_ADMIN = "test-only-admin";
+ private static final String TAG_DISABLE_CAMERA = "disable-camera";
+ private static final String TAG_DISABLE_CALLER_ID = "disable-caller-id";
+ private static final String TAG_DISABLE_CONTACTS_SEARCH = "disable-contacts-search";
+ private static final String TAG_DISABLE_BLUETOOTH_CONTACT_SHARING =
+ "disable-bt-contacts-sharing";
+ private static final String TAG_DISABLE_SCREEN_CAPTURE = "disable-screen-capture";
+ private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management";
+ private static final String TAG_REQUIRE_AUTO_TIME = "require_auto_time";
+ private static final String TAG_FORCE_EPHEMERAL_USERS = "force_ephemeral_users";
+ private static final String TAG_IS_NETWORK_LOGGING_ENABLED = "is_network_logging_enabled";
+ private static final String TAG_ACCOUNT_TYPE = "account-type";
+ private static final String TAG_PERMITTED_ACCESSIBILITY_SERVICES =
+ "permitted-accessiblity-services";
+ private static final String TAG_ENCRYPTION_REQUESTED = "encryption-requested";
+ private static final String TAG_MANAGE_TRUST_AGENT_FEATURES = "manage-trust-agent-features";
+ private static final String TAG_TRUST_AGENT_COMPONENT_OPTIONS = "trust-agent-component-options";
+ private static final String TAG_TRUST_AGENT_COMPONENT = "component";
+ private static final String TAG_PASSWORD_EXPIRATION_DATE = "password-expiration-date";
+ private static final String TAG_PASSWORD_EXPIRATION_TIMEOUT = "password-expiration-timeout";
+ private static final String TAG_GLOBAL_PROXY_EXCLUSION_LIST = "global-proxy-exclusion-list";
+ private static final String TAG_GLOBAL_PROXY_SPEC = "global-proxy-spec";
+ private static final String TAG_SPECIFIES_GLOBAL_PROXY = "specifies-global-proxy";
+ private static final String TAG_PERMITTED_IMES = "permitted-imes";
+ private static final String TAG_PERMITTED_NOTIFICATION_LISTENERS =
+ "permitted-notification-listeners";
+ private static final String TAG_MAX_FAILED_PASSWORD_WIPE = "max-failed-password-wipe";
+ private static final String TAG_MAX_TIME_TO_UNLOCK = "max-time-to-unlock";
+ private static final String TAG_STRONG_AUTH_UNLOCK_TIMEOUT = "strong-auth-unlock-timeout";
+ private static final String TAG_MIN_PASSWORD_NONLETTER = "min-password-nonletter";
+ private static final String TAG_MIN_PASSWORD_SYMBOLS = "min-password-symbols";
+ private static final String TAG_MIN_PASSWORD_NUMERIC = "min-password-numeric";
+ private static final String TAG_MIN_PASSWORD_LETTERS = "min-password-letters";
+ private static final String TAG_MIN_PASSWORD_LOWERCASE = "min-password-lowercase";
+ private static final String TAG_MIN_PASSWORD_UPPERCASE = "min-password-uppercase";
+ private static final String TAG_PASSWORD_HISTORY_LENGTH = "password-history-length";
+ private static final String TAG_MIN_PASSWORD_LENGTH = "min-password-length";
+ private static final String TAG_PASSWORD_QUALITY = "password-quality";
+ private static final String TAG_POLICIES = "policies";
+ private static final String TAG_CROSS_PROFILE_WIDGET_PROVIDERS =
+ "cross-profile-widget-providers";
+ private static final String TAG_PROVIDER = "provider";
+ private static final String TAG_PACKAGE_LIST_ITEM = "item";
+ private static final String TAG_KEEP_UNINSTALLED_PACKAGES = "keep-uninstalled-packages";
+ private static final String TAG_USER_RESTRICTIONS = "user-restrictions";
+ private static final String TAG_DEFAULT_ENABLED_USER_RESTRICTIONS =
+ "default-enabled-user-restrictions";
+ private static final String TAG_RESTRICTION = "restriction";
+ private static final String TAG_SHORT_SUPPORT_MESSAGE = "short-support-message";
+ private static final String TAG_LONG_SUPPORT_MESSAGE = "long-support-message";
+ private static final String TAG_PARENT_ADMIN = "parent-admin";
+ private static final String TAG_ORGANIZATION_COLOR = "organization-color";
+ private static final String TAG_ORGANIZATION_NAME = "organization-name";
+ private static final String TAG_IS_LOGOUT_ENABLED = "is_logout_enabled";
+ private static final String TAG_START_USER_SESSION_MESSAGE = "start_user_session_message";
+ private static final String TAG_END_USER_SESSION_MESSAGE = "end_user_session_message";
+ private static final String TAG_METERED_DATA_DISABLED_PACKAGES =
+ "metered_data_disabled_packages";
+ private static final String TAG_CROSS_PROFILE_CALENDAR_PACKAGES =
+ "cross-profile-calendar-packages";
+ private static final String TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL =
+ "cross-profile-calendar-packages-null";
+ private static final String TAG_CROSS_PROFILE_PACKAGES = "cross-profile-packages";
+ private static final String TAG_FACTORY_RESET_PROTECTION_POLICY =
+ "factory_reset_protection_policy";
+ private static final String TAG_SUSPEND_PERSONAL_APPS = "suspend-personal-apps";
+ private static final String TAG_PROFILE_MAXIMUM_TIME_OFF = "profile-max-time-off";
+ private static final String TAG_PROFILE_OFF_DEADLINE = "profile-off-deadline";
+ private static final String TAG_ALWAYS_ON_VPN_PACKAGE = "vpn-package";
+ private static final String TAG_ALWAYS_ON_VPN_LOCKDOWN = "vpn-lockdown";
+ private static final String TAG_COMMON_CRITERIA_MODE = "common-criteria-mode";
+ private static final String ATTR_VALUE = "value";
+ private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification";
+ private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications";
+
+ DeviceAdminInfo info;
+
+ static final int DEF_PASSWORD_HISTORY_LENGTH = 0;
+ int passwordHistoryLength = DEF_PASSWORD_HISTORY_LENGTH;
+
+ @NonNull
+ PasswordPolicy mPasswordPolicy = new PasswordPolicy();
+
+ @Nullable
+ FactoryResetProtectionPolicy mFactoryResetProtectionPolicy = null;
+
+ static final long DEF_MAXIMUM_TIME_TO_UNLOCK = 0;
+ long maximumTimeToUnlock = DEF_MAXIMUM_TIME_TO_UNLOCK;
+
+ long strongAuthUnlockTimeout = 0; // admin doesn't participate by default
+
+ static final int DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE = 0;
+ int maximumFailedPasswordsForWipe = DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE;
+
+ static final long DEF_PASSWORD_EXPIRATION_TIMEOUT = 0;
+ long passwordExpirationTimeout = DEF_PASSWORD_EXPIRATION_TIMEOUT;
+
+ static final long DEF_PASSWORD_EXPIRATION_DATE = 0;
+ long passwordExpirationDate = DEF_PASSWORD_EXPIRATION_DATE;
+
+ static final int DEF_KEYGUARD_FEATURES_DISABLED = 0; // none
+
+ int disabledKeyguardFeatures = DEF_KEYGUARD_FEATURES_DISABLED;
+
+ boolean encryptionRequested = false;
+ boolean testOnlyAdmin = false;
+ boolean disableCamera = false;
+ boolean disableCallerId = false;
+ boolean disableContactsSearch = false;
+ boolean disableBluetoothContactSharing = true;
+ boolean disableScreenCapture = false;
+ boolean requireAutoTime = false;
+ boolean forceEphemeralUsers = false;
+ boolean isNetworkLoggingEnabled = false;
+ boolean isLogoutEnabled = false;
+
+ // one notification after enabling + one more after reboots
+ static final int DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN = 2;
+ int numNetworkLoggingNotifications = 0;
+ long lastNetworkLoggingNotificationTimeMs = 0; // Time in milliseconds since epoch
+
+ ActiveAdmin parentAdmin;
+ final boolean isParent;
+
+ static class TrustAgentInfo {
+ public PersistableBundle options;
+ TrustAgentInfo(PersistableBundle bundle) {
+ options = bundle;
+ }
+ }
+
+ // The list of packages which are not allowed to use metered data.
+ List<String> meteredDisabledPackages;
+
+ final Set<String> accountTypesWithManagementDisabled = new ArraySet<>();
+
+ // The list of permitted accessibility services package namesas set by a profile
+ // or device owner. Null means all accessibility services are allowed, empty means
+ // none except system services are allowed.
+ List<String> permittedAccessiblityServices;
+
+ // The list of permitted input methods package names as set by a profile or device owner.
+ // Null means all input methods are allowed, empty means none except system imes are
+ // allowed.
+ List<String> permittedInputMethods;
+
+ // The list of packages allowed to use a NotificationListenerService to receive events for
+ // notifications from this user. Null means that all packages are allowed. Empty list means
+ // that only packages from the system are allowed.
+ List<String> permittedNotificationListeners;
+
+ // List of package names to keep cached.
+ List<String> keepUninstalledPackages;
+
+ // TODO: review implementation decisions with frameworks team
+ boolean specifiesGlobalProxy = false;
+ String globalProxySpec = null;
+ String globalProxyExclusionList = null;
+
+ @NonNull
+ ArrayMap<String, TrustAgentInfo> trustAgentInfos = new ArrayMap<>();
+
+ List<String> crossProfileWidgetProviders;
+
+ Bundle userRestrictions;
+
+ // User restrictions that have already been enabled by default for this admin (either when
+ // setting the device or profile owner, or during a system update if one of those "enabled
+ // by default" restrictions is newly added).
+ final Set<String> defaultEnabledRestrictionsAlreadySet = new ArraySet<>();
+
+ // Support text provided by the admin to display to the user.
+ CharSequence shortSupportMessage = null;
+ CharSequence longSupportMessage = null;
+
+ // Background color of confirm credentials screen. Default: teal.
+ static final int DEF_ORGANIZATION_COLOR = Color.parseColor("#00796B");
+ int organizationColor = DEF_ORGANIZATION_COLOR;
+
+ // Default title of confirm credentials screen
+ String organizationName = null;
+
+ // Message for user switcher
+ String startUserSessionMessage = null;
+ String endUserSessionMessage = null;
+
+ // The allow list of packages that can access cross profile calendar APIs.
+ // This allow list should be in default an empty list, which indicates that no package
+ // is allow listed.
+ List<String> mCrossProfileCalendarPackages = Collections.emptyList();
+
+ // The allow list of packages that the admin has enabled to be able to request consent from
+ // the user to communicate cross-profile. By default, no packages are allowed, which is
+ // represented as an empty list.
+ List<String> mCrossProfilePackages = Collections.emptyList();
+
+ // Whether the admin explicitly requires personal apps to be suspended
+ boolean mSuspendPersonalApps = false;
+ // Maximum time the profile owned by this admin can be off.
+ long mProfileMaximumTimeOffMillis = 0;
+ // Time by which the profile should be turned on according to System.currentTimeMillis().
+ long mProfileOffDeadline = 0;
+
+ public String mAlwaysOnVpnPackage;
+ public boolean mAlwaysOnVpnLockdown;
+ boolean mCommonCriteriaMode;
+
+ ActiveAdmin(DeviceAdminInfo info, boolean isParent) {
+ this.info = info;
+ this.isParent = isParent;
+ }
+
+ ActiveAdmin getParentActiveAdmin() {
+ Preconditions.checkState(!isParent);
+
+ if (parentAdmin == null) {
+ parentAdmin = new ActiveAdmin(info, /* parent */ true);
+ }
+ return parentAdmin;
+ }
+
+ boolean hasParentActiveAdmin() {
+ return parentAdmin != null;
+ }
+
+ int getUid() {
+ return info.getActivityInfo().applicationInfo.uid;
+ }
+
+ public UserHandle getUserHandle() {
+ return UserHandle.of(UserHandle.getUserId(info.getActivityInfo().applicationInfo.uid));
+ }
+
+ void writeToXml(XmlSerializer out)
+ throws IllegalArgumentException, IllegalStateException, IOException {
+ out.startTag(null, TAG_POLICIES);
+ info.writePoliciesToXml(out);
+ out.endTag(null, TAG_POLICIES);
+ if (mPasswordPolicy.quality != PASSWORD_QUALITY_UNSPECIFIED) {
+ writeAttributeValueToXml(
+ out, TAG_PASSWORD_QUALITY, mPasswordPolicy.quality);
+ if (mPasswordPolicy.length != PasswordPolicy.DEF_MINIMUM_LENGTH) {
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_LENGTH, mPasswordPolicy.length);
+ }
+ if (mPasswordPolicy.upperCase != PasswordPolicy.DEF_MINIMUM_UPPER_CASE) {
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_UPPERCASE, mPasswordPolicy.upperCase);
+ }
+ if (mPasswordPolicy.lowerCase != PasswordPolicy.DEF_MINIMUM_LOWER_CASE) {
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_LOWERCASE, mPasswordPolicy.lowerCase);
+ }
+ if (mPasswordPolicy.letters != PasswordPolicy.DEF_MINIMUM_LETTERS) {
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_LETTERS, mPasswordPolicy.letters);
+ }
+ if (mPasswordPolicy.numeric != PasswordPolicy.DEF_MINIMUM_NUMERIC) {
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_NUMERIC, mPasswordPolicy.numeric);
+ }
+ if (mPasswordPolicy.symbols != PasswordPolicy.DEF_MINIMUM_SYMBOLS) {
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_SYMBOLS, mPasswordPolicy.symbols);
+ }
+ if (mPasswordPolicy.nonLetter > PasswordPolicy.DEF_MINIMUM_NON_LETTER) {
+ writeAttributeValueToXml(
+ out, TAG_MIN_PASSWORD_NONLETTER, mPasswordPolicy.nonLetter);
+ }
+ }
+ if (passwordHistoryLength != DEF_PASSWORD_HISTORY_LENGTH) {
+ writeAttributeValueToXml(
+ out, TAG_PASSWORD_HISTORY_LENGTH, passwordHistoryLength);
+ }
+ if (maximumTimeToUnlock != DEF_MAXIMUM_TIME_TO_UNLOCK) {
+ writeAttributeValueToXml(
+ out, TAG_MAX_TIME_TO_UNLOCK, maximumTimeToUnlock);
+ }
+ if (strongAuthUnlockTimeout != DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS) {
+ writeAttributeValueToXml(
+ out, TAG_STRONG_AUTH_UNLOCK_TIMEOUT, strongAuthUnlockTimeout);
+ }
+ if (maximumFailedPasswordsForWipe != DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) {
+ writeAttributeValueToXml(
+ out, TAG_MAX_FAILED_PASSWORD_WIPE, maximumFailedPasswordsForWipe);
+ }
+ if (specifiesGlobalProxy) {
+ writeAttributeValueToXml(
+ out, TAG_SPECIFIES_GLOBAL_PROXY, specifiesGlobalProxy);
+ if (globalProxySpec != null) {
+ writeAttributeValueToXml(out, TAG_GLOBAL_PROXY_SPEC, globalProxySpec);
+ }
+ if (globalProxyExclusionList != null) {
+ writeAttributeValueToXml(
+ out, TAG_GLOBAL_PROXY_EXCLUSION_LIST, globalProxyExclusionList);
+ }
+ }
+ if (passwordExpirationTimeout != DEF_PASSWORD_EXPIRATION_TIMEOUT) {
+ writeAttributeValueToXml(
+ out, TAG_PASSWORD_EXPIRATION_TIMEOUT, passwordExpirationTimeout);
+ }
+ if (passwordExpirationDate != DEF_PASSWORD_EXPIRATION_DATE) {
+ writeAttributeValueToXml(
+ out, TAG_PASSWORD_EXPIRATION_DATE, passwordExpirationDate);
+ }
+ if (encryptionRequested) {
+ writeAttributeValueToXml(
+ out, TAG_ENCRYPTION_REQUESTED, encryptionRequested);
+ }
+ if (testOnlyAdmin) {
+ writeAttributeValueToXml(
+ out, TAG_TEST_ONLY_ADMIN, testOnlyAdmin);
+ }
+ if (disableCamera) {
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_CAMERA, disableCamera);
+ }
+ if (disableCallerId) {
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_CALLER_ID, disableCallerId);
+ }
+ if (disableContactsSearch) {
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_CONTACTS_SEARCH, disableContactsSearch);
+ }
+ if (!disableBluetoothContactSharing) {
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_BLUETOOTH_CONTACT_SHARING, disableBluetoothContactSharing);
+ }
+ if (disableScreenCapture) {
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_SCREEN_CAPTURE, disableScreenCapture);
+ }
+ if (requireAutoTime) {
+ writeAttributeValueToXml(
+ out, TAG_REQUIRE_AUTO_TIME, requireAutoTime);
+ }
+ if (forceEphemeralUsers) {
+ writeAttributeValueToXml(
+ out, TAG_FORCE_EPHEMERAL_USERS, forceEphemeralUsers);
+ }
+ if (isNetworkLoggingEnabled) {
+ out.startTag(null, TAG_IS_NETWORK_LOGGING_ENABLED);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(isNetworkLoggingEnabled));
+ out.attribute(null, ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS,
+ Integer.toString(numNetworkLoggingNotifications));
+ out.attribute(null, ATTR_LAST_NETWORK_LOGGING_NOTIFICATION,
+ Long.toString(lastNetworkLoggingNotificationTimeMs));
+ out.endTag(null, TAG_IS_NETWORK_LOGGING_ENABLED);
+ }
+ if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) {
+ writeAttributeValueToXml(
+ out, TAG_DISABLE_KEYGUARD_FEATURES, disabledKeyguardFeatures);
+ }
+ if (!accountTypesWithManagementDisabled.isEmpty()) {
+ writeAttributeValuesToXml(
+ out, TAG_DISABLE_ACCOUNT_MANAGEMENT, TAG_ACCOUNT_TYPE,
+ accountTypesWithManagementDisabled);
+ }
+ if (!trustAgentInfos.isEmpty()) {
+ Set<Map.Entry<String, TrustAgentInfo>> set = trustAgentInfos.entrySet();
+ out.startTag(null, TAG_MANAGE_TRUST_AGENT_FEATURES);
+ for (Map.Entry<String, TrustAgentInfo> entry : set) {
+ TrustAgentInfo trustAgentInfo = entry.getValue();
+ out.startTag(null, TAG_TRUST_AGENT_COMPONENT);
+ out.attribute(null, ATTR_VALUE, entry.getKey());
+ if (trustAgentInfo.options != null) {
+ out.startTag(null, TAG_TRUST_AGENT_COMPONENT_OPTIONS);
+ try {
+ trustAgentInfo.options.saveToXml(out);
+ } catch (XmlPullParserException e) {
+ Log.e(DevicePolicyManagerService.LOG_TAG,
+ "Failed to save TrustAgent options", e);
+ }
+ out.endTag(null, TAG_TRUST_AGENT_COMPONENT_OPTIONS);
+ }
+ out.endTag(null, TAG_TRUST_AGENT_COMPONENT);
+ }
+ out.endTag(null, TAG_MANAGE_TRUST_AGENT_FEATURES);
+ }
+ if (crossProfileWidgetProviders != null && !crossProfileWidgetProviders.isEmpty()) {
+ writeAttributeValuesToXml(
+ out, TAG_CROSS_PROFILE_WIDGET_PROVIDERS, TAG_PROVIDER,
+ crossProfileWidgetProviders);
+ }
+ writePackageListToXml(out, TAG_PERMITTED_ACCESSIBILITY_SERVICES,
+ permittedAccessiblityServices);
+ writePackageListToXml(out, TAG_PERMITTED_IMES, permittedInputMethods);
+ writePackageListToXml(out, TAG_PERMITTED_NOTIFICATION_LISTENERS,
+ permittedNotificationListeners);
+ writePackageListToXml(out, TAG_KEEP_UNINSTALLED_PACKAGES, keepUninstalledPackages);
+ writePackageListToXml(out, TAG_METERED_DATA_DISABLED_PACKAGES, meteredDisabledPackages);
+ if (hasUserRestrictions()) {
+ UserRestrictionsUtils.writeRestrictions(
+ out, userRestrictions, TAG_USER_RESTRICTIONS);
+ }
+ if (!defaultEnabledRestrictionsAlreadySet.isEmpty()) {
+ writeAttributeValuesToXml(out, TAG_DEFAULT_ENABLED_USER_RESTRICTIONS,
+ TAG_RESTRICTION,
+ defaultEnabledRestrictionsAlreadySet);
+ }
+ if (!TextUtils.isEmpty(shortSupportMessage)) {
+ writeTextToXml(out, TAG_SHORT_SUPPORT_MESSAGE, shortSupportMessage.toString());
+ }
+ if (!TextUtils.isEmpty(longSupportMessage)) {
+ writeTextToXml(out, TAG_LONG_SUPPORT_MESSAGE, longSupportMessage.toString());
+ }
+ if (parentAdmin != null) {
+ out.startTag(null, TAG_PARENT_ADMIN);
+ parentAdmin.writeToXml(out);
+ out.endTag(null, TAG_PARENT_ADMIN);
+ }
+ if (organizationColor != DEF_ORGANIZATION_COLOR) {
+ writeAttributeValueToXml(out, TAG_ORGANIZATION_COLOR, organizationColor);
+ }
+ if (organizationName != null) {
+ writeTextToXml(out, TAG_ORGANIZATION_NAME, organizationName);
+ }
+ if (isLogoutEnabled) {
+ writeAttributeValueToXml(out, TAG_IS_LOGOUT_ENABLED, isLogoutEnabled);
+ }
+ if (startUserSessionMessage != null) {
+ writeTextToXml(out, TAG_START_USER_SESSION_MESSAGE, startUserSessionMessage);
+ }
+ if (endUserSessionMessage != null) {
+ writeTextToXml(out, TAG_END_USER_SESSION_MESSAGE, endUserSessionMessage);
+ }
+ if (mCrossProfileCalendarPackages == null) {
+ out.startTag(null, TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL);
+ out.endTag(null, TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL);
+ } else {
+ writePackageListToXml(out, TAG_CROSS_PROFILE_CALENDAR_PACKAGES,
+ mCrossProfileCalendarPackages);
+ }
+ writePackageListToXml(out, TAG_CROSS_PROFILE_PACKAGES, mCrossProfilePackages);
+ if (mFactoryResetProtectionPolicy != null) {
+ out.startTag(null, TAG_FACTORY_RESET_PROTECTION_POLICY);
+ mFactoryResetProtectionPolicy.writeToXml(out);
+ out.endTag(null, TAG_FACTORY_RESET_PROTECTION_POLICY);
+ }
+ if (mSuspendPersonalApps) {
+ writeAttributeValueToXml(out, TAG_SUSPEND_PERSONAL_APPS, mSuspendPersonalApps);
+ }
+ if (mProfileMaximumTimeOffMillis != 0) {
+ writeAttributeValueToXml(out, TAG_PROFILE_MAXIMUM_TIME_OFF,
+ mProfileMaximumTimeOffMillis);
+ }
+ if (mProfileMaximumTimeOffMillis != 0) {
+ writeAttributeValueToXml(out, TAG_PROFILE_OFF_DEADLINE, mProfileOffDeadline);
+ }
+ if (!TextUtils.isEmpty(mAlwaysOnVpnPackage)) {
+ writeAttributeValueToXml(out, TAG_ALWAYS_ON_VPN_PACKAGE, mAlwaysOnVpnPackage);
+ }
+ if (mAlwaysOnVpnLockdown) {
+ writeAttributeValueToXml(out, TAG_ALWAYS_ON_VPN_LOCKDOWN, mAlwaysOnVpnLockdown);
+ }
+ if (mCommonCriteriaMode) {
+ writeAttributeValueToXml(out, TAG_COMMON_CRITERIA_MODE, mCommonCriteriaMode);
+ }
+ }
+
+ void writeTextToXml(XmlSerializer out, String tag, String text) throws IOException {
+ out.startTag(null, tag);
+ out.text(text);
+ out.endTag(null, tag);
+ }
+
+ void writePackageListToXml(XmlSerializer out, String outerTag,
+ List<String> packageList)
+ throws IllegalArgumentException, IllegalStateException, IOException {
+ if (packageList == null) {
+ return;
+ }
+ writeAttributeValuesToXml(out, outerTag, TAG_PACKAGE_LIST_ITEM, packageList);
+ }
+
+ void writeAttributeValueToXml(XmlSerializer out, String tag, String value)
+ throws IOException {
+ out.startTag(null, tag);
+ out.attribute(null, ATTR_VALUE, value);
+ out.endTag(null, tag);
+ }
+
+ void writeAttributeValueToXml(XmlSerializer out, String tag, int value)
+ throws IOException {
+ out.startTag(null, tag);
+ out.attribute(null, ATTR_VALUE, Integer.toString(value));
+ out.endTag(null, tag);
+ }
+
+ void writeAttributeValueToXml(XmlSerializer out, String tag, long value)
+ throws IOException {
+ out.startTag(null, tag);
+ out.attribute(null, ATTR_VALUE, Long.toString(value));
+ out.endTag(null, tag);
+ }
+
+ void writeAttributeValueToXml(XmlSerializer out, String tag, boolean value)
+ throws IOException {
+ out.startTag(null, tag);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(value));
+ out.endTag(null, tag);
+ }
+
+ void writeAttributeValuesToXml(XmlSerializer out, String outerTag, String innerTag,
+ @NonNull Collection<String> values) throws IOException {
+ out.startTag(null, outerTag);
+ for (String value : values) {
+ out.startTag(null, innerTag);
+ out.attribute(null, ATTR_VALUE, value);
+ out.endTag(null, innerTag);
+ }
+ out.endTag(null, outerTag);
+ }
+
+ void readFromXml(XmlPullParser parser, boolean shouldOverridePolicies)
+ throws XmlPullParserException, IOException {
+ int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != END_DOCUMENT
+ && (type != END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == END_TAG || type == TEXT) {
+ continue;
+ }
+ String tag = parser.getName();
+ if (TAG_POLICIES.equals(tag)) {
+ if (shouldOverridePolicies) {
+ Log.d(DevicePolicyManagerService.LOG_TAG,
+ "Overriding device admin policies from XML.");
+ info.readPoliciesFromXml(parser);
+ }
+ } else if (TAG_PASSWORD_QUALITY.equals(tag)) {
+ mPasswordPolicy.quality = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_LENGTH.equals(tag)) {
+ mPasswordPolicy.length = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_PASSWORD_HISTORY_LENGTH.equals(tag)) {
+ passwordHistoryLength = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_UPPERCASE.equals(tag)) {
+ mPasswordPolicy.upperCase = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_LOWERCASE.equals(tag)) {
+ mPasswordPolicy.lowerCase = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_LETTERS.equals(tag)) {
+ mPasswordPolicy.letters = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_NUMERIC.equals(tag)) {
+ mPasswordPolicy.numeric = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_SYMBOLS.equals(tag)) {
+ mPasswordPolicy.symbols = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MIN_PASSWORD_NONLETTER.equals(tag)) {
+ mPasswordPolicy.nonLetter = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MAX_TIME_TO_UNLOCK.equals(tag)) {
+ maximumTimeToUnlock = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_STRONG_AUTH_UNLOCK_TIMEOUT.equals(tag)) {
+ strongAuthUnlockTimeout = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_MAX_FAILED_PASSWORD_WIPE.equals(tag)) {
+ maximumFailedPasswordsForWipe = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_SPECIFIES_GLOBAL_PROXY.equals(tag)) {
+ specifiesGlobalProxy = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_GLOBAL_PROXY_SPEC.equals(tag)) {
+ globalProxySpec =
+ parser.getAttributeValue(null, ATTR_VALUE);
+ } else if (TAG_GLOBAL_PROXY_EXCLUSION_LIST.equals(tag)) {
+ globalProxyExclusionList =
+ parser.getAttributeValue(null, ATTR_VALUE);
+ } else if (TAG_PASSWORD_EXPIRATION_TIMEOUT.equals(tag)) {
+ passwordExpirationTimeout = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_PASSWORD_EXPIRATION_DATE.equals(tag)) {
+ passwordExpirationDate = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_ENCRYPTION_REQUESTED.equals(tag)) {
+ encryptionRequested = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_TEST_ONLY_ADMIN.equals(tag)) {
+ testOnlyAdmin = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_DISABLE_CAMERA.equals(tag)) {
+ disableCamera = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_DISABLE_CALLER_ID.equals(tag)) {
+ disableCallerId = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_DISABLE_CONTACTS_SEARCH.equals(tag)) {
+ disableContactsSearch = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_DISABLE_BLUETOOTH_CONTACT_SHARING.equals(tag)) {
+ disableBluetoothContactSharing = Boolean.parseBoolean(parser
+ .getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_DISABLE_SCREEN_CAPTURE.equals(tag)) {
+ disableScreenCapture = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_REQUIRE_AUTO_TIME.equals(tag)) {
+ requireAutoTime = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_FORCE_EPHEMERAL_USERS.equals(tag)) {
+ forceEphemeralUsers = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_IS_NETWORK_LOGGING_ENABLED.equals(tag)) {
+ isNetworkLoggingEnabled = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ lastNetworkLoggingNotificationTimeMs = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_LAST_NETWORK_LOGGING_NOTIFICATION));
+ numNetworkLoggingNotifications = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS));
+ } else if (TAG_DISABLE_KEYGUARD_FEATURES.equals(tag)) {
+ disabledKeyguardFeatures = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_DISABLE_ACCOUNT_MANAGEMENT.equals(tag)) {
+ readAttributeValues(
+ parser, TAG_ACCOUNT_TYPE, accountTypesWithManagementDisabled);
+ } else if (TAG_MANAGE_TRUST_AGENT_FEATURES.equals(tag)) {
+ trustAgentInfos = getAllTrustAgentInfos(parser, tag);
+ } else if (TAG_CROSS_PROFILE_WIDGET_PROVIDERS.equals(tag)) {
+ crossProfileWidgetProviders = new ArrayList<>();
+ readAttributeValues(parser, TAG_PROVIDER, crossProfileWidgetProviders);
+ } else if (TAG_PERMITTED_ACCESSIBILITY_SERVICES.equals(tag)) {
+ permittedAccessiblityServices = readPackageList(parser, tag);
+ } else if (TAG_PERMITTED_IMES.equals(tag)) {
+ permittedInputMethods = readPackageList(parser, tag);
+ } else if (TAG_PERMITTED_NOTIFICATION_LISTENERS.equals(tag)) {
+ permittedNotificationListeners = readPackageList(parser, tag);
+ } else if (TAG_KEEP_UNINSTALLED_PACKAGES.equals(tag)) {
+ keepUninstalledPackages = readPackageList(parser, tag);
+ } else if (TAG_METERED_DATA_DISABLED_PACKAGES.equals(tag)) {
+ meteredDisabledPackages = readPackageList(parser, tag);
+ } else if (TAG_USER_RESTRICTIONS.equals(tag)) {
+ userRestrictions = UserRestrictionsUtils.readRestrictions(parser);
+ } else if (TAG_DEFAULT_ENABLED_USER_RESTRICTIONS.equals(tag)) {
+ readAttributeValues(
+ parser, TAG_RESTRICTION, defaultEnabledRestrictionsAlreadySet);
+ } else if (TAG_SHORT_SUPPORT_MESSAGE.equals(tag)) {
+ type = parser.next();
+ if (type == XmlPullParser.TEXT) {
+ shortSupportMessage = parser.getText();
+ } else {
+ Log.w(DevicePolicyManagerService.LOG_TAG,
+ "Missing text when loading short support message");
+ }
+ } else if (TAG_LONG_SUPPORT_MESSAGE.equals(tag)) {
+ type = parser.next();
+ if (type == XmlPullParser.TEXT) {
+ longSupportMessage = parser.getText();
+ } else {
+ Log.w(DevicePolicyManagerService.LOG_TAG,
+ "Missing text when loading long support message");
+ }
+ } else if (TAG_PARENT_ADMIN.equals(tag)) {
+ Preconditions.checkState(!isParent);
+ parentAdmin = new ActiveAdmin(info, /* parent */ true);
+ parentAdmin.readFromXml(parser, shouldOverridePolicies);
+ } else if (TAG_ORGANIZATION_COLOR.equals(tag)) {
+ organizationColor = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_ORGANIZATION_NAME.equals(tag)) {
+ type = parser.next();
+ if (type == XmlPullParser.TEXT) {
+ organizationName = parser.getText();
+ } else {
+ Log.w(DevicePolicyManagerService.LOG_TAG,
+ "Missing text when loading organization name");
+ }
+ } else if (TAG_IS_LOGOUT_ENABLED.equals(tag)) {
+ isLogoutEnabled = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_START_USER_SESSION_MESSAGE.equals(tag)) {
+ type = parser.next();
+ if (type == XmlPullParser.TEXT) {
+ startUserSessionMessage = parser.getText();
+ } else {
+ Log.w(DevicePolicyManagerService.LOG_TAG,
+ "Missing text when loading start session message");
+ }
+ } else if (TAG_END_USER_SESSION_MESSAGE.equals(tag)) {
+ type = parser.next();
+ if (type == XmlPullParser.TEXT) {
+ endUserSessionMessage = parser.getText();
+ } else {
+ Log.w(DevicePolicyManagerService.LOG_TAG,
+ "Missing text when loading end session message");
+ }
+ } else if (TAG_CROSS_PROFILE_CALENDAR_PACKAGES.equals(tag)) {
+ mCrossProfileCalendarPackages = readPackageList(parser, tag);
+ } else if (TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL.equals(tag)) {
+ mCrossProfileCalendarPackages = null;
+ } else if (TAG_CROSS_PROFILE_PACKAGES.equals(tag)) {
+ mCrossProfilePackages = readPackageList(parser, tag);
+ } else if (TAG_FACTORY_RESET_PROTECTION_POLICY.equals(tag)) {
+ mFactoryResetProtectionPolicy = FactoryResetProtectionPolicy.readFromXml(
+ parser);
+ } else if (TAG_SUSPEND_PERSONAL_APPS.equals(tag)) {
+ mSuspendPersonalApps = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_PROFILE_MAXIMUM_TIME_OFF.equals(tag)) {
+ mProfileMaximumTimeOffMillis =
+ Long.parseLong(parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_PROFILE_OFF_DEADLINE.equals(tag)) {
+ mProfileOffDeadline =
+ Long.parseLong(parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_ALWAYS_ON_VPN_PACKAGE.equals(tag)) {
+ mAlwaysOnVpnPackage = parser.getAttributeValue(null, ATTR_VALUE);
+ } else if (TAG_ALWAYS_ON_VPN_LOCKDOWN.equals(tag)) {
+ mAlwaysOnVpnLockdown = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_COMMON_CRITERIA_MODE.equals(tag)) {
+ mCommonCriteriaMode = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else {
+ Slog.w(DevicePolicyManagerService.LOG_TAG, "Unknown admin tag: " + tag);
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+ }
+
+ private List<String> readPackageList(XmlPullParser parser,
+ String tag) throws XmlPullParserException, IOException {
+ List<String> result = new ArrayList<String>();
+ int outerDepth = parser.getDepth();
+ int outerType;
+ while ((outerType = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (outerType != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (outerType == XmlPullParser.END_TAG || outerType == XmlPullParser.TEXT) {
+ continue;
+ }
+ String outerTag = parser.getName();
+ if (TAG_PACKAGE_LIST_ITEM.equals(outerTag)) {
+ String packageName = parser.getAttributeValue(null, ATTR_VALUE);
+ if (packageName != null) {
+ result.add(packageName);
+ } else {
+ Slog.w(DevicePolicyManagerService.LOG_TAG,
+ "Package name missing under " + outerTag);
+ }
+ } else {
+ Slog.w(DevicePolicyManagerService.LOG_TAG,
+ "Unknown tag under " + tag + ": " + outerTag);
+ }
+ }
+ return result;
+ }
+
+ private void readAttributeValues(
+ XmlPullParser parser, String tag, Collection<String> result)
+ throws XmlPullParserException, IOException {
+ result.clear();
+ int outerDepthDAM = parser.getDepth();
+ int typeDAM;
+ while ((typeDAM = parser.next()) != END_DOCUMENT
+ && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
+ if (typeDAM == END_TAG || typeDAM == TEXT) {
+ continue;
+ }
+ String tagDAM = parser.getName();
+ if (tag.equals(tagDAM)) {
+ result.add(parser.getAttributeValue(null, ATTR_VALUE));
+ } else {
+ Slog.e(DevicePolicyManagerService.LOG_TAG,
+ "Expected tag " + tag + " but found " + tagDAM);
+ }
+ }
+ }
+
+ @NonNull
+ private ArrayMap<String, TrustAgentInfo> getAllTrustAgentInfos(
+ XmlPullParser parser, String tag) throws XmlPullParserException, IOException {
+ int outerDepthDAM = parser.getDepth();
+ int typeDAM;
+ final ArrayMap<String, TrustAgentInfo> result = new ArrayMap<>();
+ while ((typeDAM = parser.next()) != END_DOCUMENT
+ && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
+ if (typeDAM == END_TAG || typeDAM == TEXT) {
+ continue;
+ }
+ String tagDAM = parser.getName();
+ if (TAG_TRUST_AGENT_COMPONENT.equals(tagDAM)) {
+ final String component = parser.getAttributeValue(null, ATTR_VALUE);
+ final TrustAgentInfo trustAgentInfo = getTrustAgentInfo(parser, tag);
+ result.put(component, trustAgentInfo);
+ } else {
+ Slog.w(DevicePolicyManagerService.LOG_TAG,
+ "Unknown tag under " + tag + ": " + tagDAM);
+ }
+ }
+ return result;
+ }
+
+ private TrustAgentInfo getTrustAgentInfo(XmlPullParser parser, String tag)
+ throws XmlPullParserException, IOException {
+ int outerDepthDAM = parser.getDepth();
+ int typeDAM;
+ TrustAgentInfo result = new TrustAgentInfo(null);
+ while ((typeDAM = parser.next()) != END_DOCUMENT
+ && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
+ if (typeDAM == END_TAG || typeDAM == TEXT) {
+ continue;
+ }
+ String tagDAM = parser.getName();
+ if (TAG_TRUST_AGENT_COMPONENT_OPTIONS.equals(tagDAM)) {
+ result.options = PersistableBundle.restoreFromXml(parser);
+ } else {
+ Slog.w(DevicePolicyManagerService.LOG_TAG,
+ "Unknown tag under " + tag + ": " + tagDAM);
+ }
+ }
+ return result;
+ }
+
+ boolean hasUserRestrictions() {
+ return userRestrictions != null && userRestrictions.size() > 0;
+ }
+
+ Bundle ensureUserRestrictions() {
+ if (userRestrictions == null) {
+ userRestrictions = new Bundle();
+ }
+ return userRestrictions;
+ }
+
+ public void transfer(DeviceAdminInfo deviceAdminInfo) {
+ if (hasParentActiveAdmin()) {
+ parentAdmin.info = deviceAdminInfo;
+ }
+ info = deviceAdminInfo;
+ }
+
+ Bundle addSyntheticRestrictions(Bundle restrictions) {
+ if (disableCamera) {
+ restrictions.putBoolean(UserManager.DISALLOW_CAMERA, true);
+ }
+ if (requireAutoTime) {
+ restrictions.putBoolean(UserManager.DISALLOW_CONFIG_DATE_TIME, true);
+ }
+ return restrictions;
+ }
+
+ static Bundle removeDeprecatedRestrictions(Bundle restrictions) {
+ for (String deprecatedRestriction: UserRestrictionsUtils.DEPRECATED_USER_RESTRICTIONS) {
+ restrictions.remove(deprecatedRestriction);
+ }
+ return restrictions;
+ }
+
+ static Bundle filterRestrictions(Bundle restrictions, Predicate<String> filter) {
+ Bundle result = new Bundle();
+ for (String key : restrictions.keySet()) {
+ if (!restrictions.getBoolean(key)) {
+ continue;
+ }
+ if (filter.test(key)) {
+ result.putBoolean(key, true);
+ }
+ }
+ return result;
+ }
+
+ Bundle getEffectiveRestrictions() {
+ return addSyntheticRestrictions(
+ removeDeprecatedRestrictions(new Bundle(ensureUserRestrictions())));
+ }
+
+ Bundle getLocalUserRestrictions(int adminType) {
+ return filterRestrictions(getEffectiveRestrictions(),
+ key -> UserRestrictionsUtils.isLocal(adminType, key));
+ }
+
+ Bundle getGlobalUserRestrictions(int adminType) {
+ return filterRestrictions(getEffectiveRestrictions(),
+ key -> UserRestrictionsUtils.isGlobal(adminType, key));
+ }
+
+ void dump(IndentingPrintWriter pw) {
+ pw.print("uid=");
+ pw.println(getUid());
+
+ pw.print("testOnlyAdmin=");
+ pw.println(testOnlyAdmin);
+
+ pw.println("policies:");
+ ArrayList<DeviceAdminInfo.PolicyInfo> pols = info.getUsedPolicies();
+ if (pols != null) {
+ pw.increaseIndent();
+ for (int i = 0; i < pols.size(); i++) {
+ pw.println(pols.get(i).tag);
+ }
+ pw.decreaseIndent();
+ }
+
+ pw.print("passwordQuality=0x");
+ pw.println(Integer.toHexString(mPasswordPolicy.quality));
+
+ pw.print("minimumPasswordLength=");
+ pw.println(mPasswordPolicy.length);
+
+ pw.print("passwordHistoryLength=");
+ pw.println(passwordHistoryLength);
+
+ pw.print("minimumPasswordUpperCase=");
+ pw.println(mPasswordPolicy.upperCase);
+
+ pw.print("minimumPasswordLowerCase=");
+ pw.println(mPasswordPolicy.lowerCase);
+
+ pw.print("minimumPasswordLetters=");
+ pw.println(mPasswordPolicy.letters);
+
+ pw.print("minimumPasswordNumeric=");
+ pw.println(mPasswordPolicy.numeric);
+
+ pw.print("minimumPasswordSymbols=");
+ pw.println(mPasswordPolicy.symbols);
+
+ pw.print("minimumPasswordNonLetter=");
+ pw.println(mPasswordPolicy.nonLetter);
+
+ pw.print("maximumTimeToUnlock=");
+ pw.println(maximumTimeToUnlock);
+
+ pw.print("strongAuthUnlockTimeout=");
+ pw.println(strongAuthUnlockTimeout);
+
+ pw.print("maximumFailedPasswordsForWipe=");
+ pw.println(maximumFailedPasswordsForWipe);
+
+ pw.print("specifiesGlobalProxy=");
+ pw.println(specifiesGlobalProxy);
+
+ pw.print("passwordExpirationTimeout=");
+ pw.println(passwordExpirationTimeout);
+
+ pw.print("passwordExpirationDate=");
+ pw.println(passwordExpirationDate);
+
+ if (globalProxySpec != null) {
+ pw.print("globalProxySpec=");
+ pw.println(globalProxySpec);
+ }
+ if (globalProxyExclusionList != null) {
+ pw.print("globalProxyEclusionList=");
+ pw.println(globalProxyExclusionList);
+ }
+ pw.print("encryptionRequested=");
+ pw.println(encryptionRequested);
+
+ pw.print("disableCamera=");
+ pw.println(disableCamera);
+
+ pw.print("disableCallerId=");
+ pw.println(disableCallerId);
+
+ pw.print("disableContactsSearch=");
+ pw.println(disableContactsSearch);
+
+ pw.print("disableBluetoothContactSharing=");
+ pw.println(disableBluetoothContactSharing);
+
+ pw.print("disableScreenCapture=");
+ pw.println(disableScreenCapture);
+
+ pw.print("requireAutoTime=");
+ pw.println(requireAutoTime);
+
+ pw.print("forceEphemeralUsers=");
+ pw.println(forceEphemeralUsers);
+
+ pw.print("isNetworkLoggingEnabled=");
+ pw.println(isNetworkLoggingEnabled);
+
+ pw.print("disabledKeyguardFeatures=");
+ pw.println(disabledKeyguardFeatures);
+
+ pw.print("crossProfileWidgetProviders=");
+ pw.println(crossProfileWidgetProviders);
+
+ if (permittedAccessiblityServices != null) {
+ pw.print("permittedAccessibilityServices=");
+ pw.println(permittedAccessiblityServices);
+ }
+
+ if (permittedInputMethods != null) {
+ pw.print("permittedInputMethods=");
+ pw.println(permittedInputMethods);
+ }
+
+ if (permittedNotificationListeners != null) {
+ pw.print("permittedNotificationListeners=");
+ pw.println(permittedNotificationListeners);
+ }
+
+ if (keepUninstalledPackages != null) {
+ pw.print("keepUninstalledPackages=");
+ pw.println(keepUninstalledPackages);
+ }
+
+ pw.print("organizationColor=");
+ pw.println(organizationColor);
+
+ if (organizationName != null) {
+ pw.print("organizationName=");
+ pw.println(organizationName);
+ }
+
+ pw.println("userRestrictions:");
+ UserRestrictionsUtils.dumpRestrictions(pw, " ", userRestrictions);
+
+ pw.print("defaultEnabledRestrictionsAlreadySet=");
+ pw.println(defaultEnabledRestrictionsAlreadySet);
+
+ pw.print("isParent=");
+ pw.println(isParent);
+
+ if (parentAdmin != null) {
+ pw.println("parentAdmin:");
+ pw.increaseIndent();
+ parentAdmin.dump(pw);
+ pw.decreaseIndent();
+ }
+
+ if (mCrossProfileCalendarPackages != null) {
+ pw.print("mCrossProfileCalendarPackages=");
+ pw.println(mCrossProfileCalendarPackages);
+ }
+
+ pw.print("mCrossProfilePackages=");
+ pw.println(mCrossProfilePackages);
+
+ pw.print("mSuspendPersonalApps=");
+ pw.println(mSuspendPersonalApps);
+
+ pw.print("mProfileMaximumTimeOffMillis=");
+ pw.println(mProfileMaximumTimeOffMillis);
+
+ pw.print("mProfileOffDeadline=");
+ pw.println(mProfileOffDeadline);
+
+ pw.print("mAlwaysOnVpnPackage=");
+ pw.println(mAlwaysOnVpnPackage);
+
+ pw.print("mAlwaysOnVpnLockdown=");
+ pw.println(mAlwaysOnVpnLockdown);
+
+ pw.print("mCommonCriteriaMode=");
+ pw.println(mCommonCriteriaMode);
+ }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
new file mode 100644
index 000000000000..130cfd50b203
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
@@ -0,0 +1,566 @@
+/*
+ * Copyright (C) 2020 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.devicepolicy;
+
+import android.app.admin.DeviceAdminInfo;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.os.FileUtils;
+import android.os.PersistableBundle;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.JournaledFile;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Function;
+
+class DevicePolicyData {
+ private static final String TAG_ACCEPTED_CA_CERTIFICATES = "accepted-ca-certificate";
+ private static final String TAG_LOCK_TASK_COMPONENTS = "lock-task-component";
+ private static final String TAG_LOCK_TASK_FEATURES = "lock-task-features";
+ private static final String TAG_STATUS_BAR = "statusbar";
+ private static final String TAG_APPS_SUSPENDED = "apps-suspended";
+ private static final String TAG_SECONDARY_LOCK_SCREEN = "secondary-lock-screen";
+ private static final String TAG_DO_NOT_ASK_CREDENTIALS_ON_BOOT =
+ "do-not-ask-credentials-on-boot";
+ private static final String TAG_AFFILIATION_ID = "affiliation-id";
+ private static final String TAG_LAST_SECURITY_LOG_RETRIEVAL = "last-security-log-retrieval";
+ private static final String TAG_LAST_BUG_REPORT_REQUEST = "last-bug-report-request";
+ private static final String TAG_LAST_NETWORK_LOG_RETRIEVAL = "last-network-log-retrieval";
+ private static final String TAG_ADMIN_BROADCAST_PENDING = "admin-broadcast-pending";
+ private static final String TAG_CURRENT_INPUT_METHOD_SET = "current-ime-set";
+ private static final String TAG_OWNER_INSTALLED_CA_CERT = "owner-installed-ca-cert";
+ private static final String TAG_INITIALIZATION_BUNDLE = "initialization-bundle";
+ private static final String TAG_PASSWORD_VALIDITY = "password-validity";
+ private static final String TAG_PASSWORD_TOKEN_HANDLE = "password-token";
+ private static final String TAG_PROTECTED_PACKAGES = "protected-packages";
+ private static final String ATTR_VALUE = "value";
+ private static final String ATTR_ALIAS = "alias";
+ private static final String ATTR_ID = "id";
+ private static final String ATTR_PERMISSION_PROVIDER = "permission-provider";
+ private static final String ATTR_NAME = "name";
+ private static final String ATTR_DISABLED = "disabled";
+ private static final String ATTR_SETUP_COMPLETE = "setup-complete";
+ private static final String ATTR_PROVISIONING_STATE = "provisioning-state";
+ private static final String ATTR_PERMISSION_POLICY = "permission-policy";
+ private static final String ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED =
+ "device-provisioning-config-applied";
+ private static final String ATTR_DEVICE_PAIRED = "device-paired";
+
+ int mFailedPasswordAttempts = 0;
+ boolean mPasswordValidAtLastCheckpoint = true;
+
+ int mUserHandle;
+ int mPasswordOwner = -1;
+ long mLastMaximumTimeToLock = -1;
+ boolean mUserSetupComplete = false;
+ boolean mPaired = false;
+ int mUserProvisioningState;
+ int mPermissionPolicy;
+
+ boolean mDeviceProvisioningConfigApplied = false;
+
+ final ArrayMap<ComponentName, ActiveAdmin> mAdminMap = new ArrayMap<>();
+ final ArrayList<ActiveAdmin> mAdminList = new ArrayList<>();
+ final ArrayList<ComponentName> mRemovingAdmins = new ArrayList<>();
+
+ // TODO(b/35385311): Keep track of metadata in TrustedCertificateStore instead.
+ final ArraySet<String> mAcceptedCaCertificates = new ArraySet<>();
+
+ // This is the list of component allowed to start lock task mode.
+ List<String> mLockTaskPackages = new ArrayList<>();
+
+ // List of packages protected by device owner
+ List<String> mUserControlDisabledPackages = new ArrayList<>();
+
+ // Bitfield of feature flags to be enabled during LockTask mode.
+ // We default on the power button menu, in order to be consistent with pre-P behaviour.
+ int mLockTaskFeatures = DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS;
+
+ boolean mStatusBarDisabled = false;
+
+ ComponentName mRestrictionsProvider;
+
+ // Map of delegate package to delegation scopes
+ final ArrayMap<String, List<String>> mDelegationMap = new ArrayMap<>();
+
+ boolean mDoNotAskCredentialsOnBoot = false;
+
+ Set<String> mAffiliationIds = new ArraySet<>();
+
+ long mLastSecurityLogRetrievalTime = -1;
+
+ long mLastBugReportRequestTime = -1;
+
+ long mLastNetworkLogsRetrievalTime = -1;
+
+ boolean mCurrentInputMethodSet = false;
+
+ boolean mSecondaryLockscreenEnabled = false;
+
+ // TODO(b/35385311): Keep track of metadata in TrustedCertificateStore instead.
+ Set<String> mOwnerInstalledCaCerts = new ArraySet<>();
+
+ // Used for initialization of users created by createAndManageUser.
+ boolean mAdminBroadcastPending = false;
+ PersistableBundle mInitBundle = null;
+
+ long mPasswordTokenHandle = 0;
+
+ // Whether user's apps are suspended. This flag should only be written AFTER all the needed
+ // apps were suspended or unsuspended.
+ boolean mAppsSuspended = false;
+
+ DevicePolicyData(int userHandle) {
+ mUserHandle = userHandle;
+ }
+
+ /**
+ * Serializes DevicePolicyData object as XML.
+ */
+ static boolean store(DevicePolicyData policyData, JournaledFile file, boolean isFdeDevice) {
+ FileOutputStream stream = null;
+ try {
+ stream = new FileOutputStream(file.chooseForWrite(), false);
+ XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(stream, StandardCharsets.UTF_8.name());
+ out.startDocument(null, true);
+
+ out.startTag(null, "policies");
+ if (policyData.mRestrictionsProvider != null) {
+ out.attribute(null, ATTR_PERMISSION_PROVIDER,
+ policyData.mRestrictionsProvider.flattenToString());
+ }
+ if (policyData.mUserSetupComplete) {
+ out.attribute(null, ATTR_SETUP_COMPLETE,
+ Boolean.toString(true));
+ }
+ if (policyData.mPaired) {
+ out.attribute(null, ATTR_DEVICE_PAIRED,
+ Boolean.toString(true));
+ }
+ if (policyData.mDeviceProvisioningConfigApplied) {
+ out.attribute(null, ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED,
+ Boolean.toString(true));
+ }
+ if (policyData.mUserProvisioningState != DevicePolicyManager.STATE_USER_UNMANAGED) {
+ out.attribute(null, ATTR_PROVISIONING_STATE,
+ Integer.toString(policyData.mUserProvisioningState));
+ }
+ if (policyData.mPermissionPolicy != DevicePolicyManager.PERMISSION_POLICY_PROMPT) {
+ out.attribute(null, ATTR_PERMISSION_POLICY,
+ Integer.toString(policyData.mPermissionPolicy));
+ }
+
+ // Serialize delegations.
+ for (int i = 0; i < policyData.mDelegationMap.size(); ++i) {
+ final String delegatePackage = policyData.mDelegationMap.keyAt(i);
+ final List<String> scopes = policyData.mDelegationMap.valueAt(i);
+
+ // Every "delegation" tag serializes the information of one delegate-scope pair.
+ for (String scope : scopes) {
+ out.startTag(null, "delegation");
+ out.attribute(null, "delegatePackage", delegatePackage);
+ out.attribute(null, "scope", scope);
+ out.endTag(null, "delegation");
+ }
+ }
+
+ final int n = policyData.mAdminList.size();
+ for (int i = 0; i < n; i++) {
+ ActiveAdmin ap = policyData.mAdminList.get(i);
+ if (ap != null) {
+ out.startTag(null, "admin");
+ out.attribute(null, "name", ap.info.getComponent().flattenToString());
+ ap.writeToXml(out);
+ out.endTag(null, "admin");
+ }
+ }
+
+ if (policyData.mPasswordOwner >= 0) {
+ out.startTag(null, "password-owner");
+ out.attribute(null, "value", Integer.toString(policyData.mPasswordOwner));
+ out.endTag(null, "password-owner");
+ }
+
+ if (policyData.mFailedPasswordAttempts != 0) {
+ out.startTag(null, "failed-password-attempts");
+ out.attribute(null, "value", Integer.toString(policyData.mFailedPasswordAttempts));
+ out.endTag(null, "failed-password-attempts");
+ }
+
+ // For FDE devices only, we save this flag so we can report on password sufficiency
+ // before the user enters their password for the first time after a reboot. For
+ // security reasons, we don't want to store the full set of active password metrics.
+ if (isFdeDevice) {
+ out.startTag(null, TAG_PASSWORD_VALIDITY);
+ out.attribute(null, ATTR_VALUE,
+ Boolean.toString(policyData.mPasswordValidAtLastCheckpoint));
+ out.endTag(null, TAG_PASSWORD_VALIDITY);
+ }
+
+ for (int i = 0; i < policyData.mAcceptedCaCertificates.size(); i++) {
+ out.startTag(null, TAG_ACCEPTED_CA_CERTIFICATES);
+ out.attribute(null, ATTR_NAME, policyData.mAcceptedCaCertificates.valueAt(i));
+ out.endTag(null, TAG_ACCEPTED_CA_CERTIFICATES);
+ }
+
+ for (int i = 0; i < policyData.mLockTaskPackages.size(); i++) {
+ String component = policyData.mLockTaskPackages.get(i);
+ out.startTag(null, TAG_LOCK_TASK_COMPONENTS);
+ out.attribute(null, "name", component);
+ out.endTag(null, TAG_LOCK_TASK_COMPONENTS);
+ }
+
+ if (policyData.mLockTaskFeatures != DevicePolicyManager.LOCK_TASK_FEATURE_NONE) {
+ out.startTag(null, TAG_LOCK_TASK_FEATURES);
+ out.attribute(null, ATTR_VALUE, Integer.toString(policyData.mLockTaskFeatures));
+ out.endTag(null, TAG_LOCK_TASK_FEATURES);
+ }
+
+ if (policyData.mSecondaryLockscreenEnabled) {
+ out.startTag(null, TAG_SECONDARY_LOCK_SCREEN);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(true));
+ out.endTag(null, TAG_SECONDARY_LOCK_SCREEN);
+ }
+
+ if (policyData.mStatusBarDisabled) {
+ out.startTag(null, TAG_STATUS_BAR);
+ out.attribute(null, ATTR_DISABLED, Boolean.toString(policyData.mStatusBarDisabled));
+ out.endTag(null, TAG_STATUS_BAR);
+ }
+
+ if (policyData.mDoNotAskCredentialsOnBoot) {
+ out.startTag(null, TAG_DO_NOT_ASK_CREDENTIALS_ON_BOOT);
+ out.endTag(null, TAG_DO_NOT_ASK_CREDENTIALS_ON_BOOT);
+ }
+
+ for (String id : policyData.mAffiliationIds) {
+ out.startTag(null, TAG_AFFILIATION_ID);
+ out.attribute(null, ATTR_ID, id);
+ out.endTag(null, TAG_AFFILIATION_ID);
+ }
+
+ if (policyData.mLastSecurityLogRetrievalTime >= 0) {
+ out.startTag(null, TAG_LAST_SECURITY_LOG_RETRIEVAL);
+ out.attribute(null, ATTR_VALUE,
+ Long.toString(policyData.mLastSecurityLogRetrievalTime));
+ out.endTag(null, TAG_LAST_SECURITY_LOG_RETRIEVAL);
+ }
+
+ if (policyData.mLastBugReportRequestTime >= 0) {
+ out.startTag(null, TAG_LAST_BUG_REPORT_REQUEST);
+ out.attribute(null, ATTR_VALUE,
+ Long.toString(policyData.mLastBugReportRequestTime));
+ out.endTag(null, TAG_LAST_BUG_REPORT_REQUEST);
+ }
+
+ if (policyData.mLastNetworkLogsRetrievalTime >= 0) {
+ out.startTag(null, TAG_LAST_NETWORK_LOG_RETRIEVAL);
+ out.attribute(null, ATTR_VALUE,
+ Long.toString(policyData.mLastNetworkLogsRetrievalTime));
+ out.endTag(null, TAG_LAST_NETWORK_LOG_RETRIEVAL);
+ }
+
+ if (policyData.mAdminBroadcastPending) {
+ out.startTag(null, TAG_ADMIN_BROADCAST_PENDING);
+ out.attribute(null, ATTR_VALUE,
+ Boolean.toString(policyData.mAdminBroadcastPending));
+ out.endTag(null, TAG_ADMIN_BROADCAST_PENDING);
+ }
+
+ if (policyData.mInitBundle != null) {
+ out.startTag(null, TAG_INITIALIZATION_BUNDLE);
+ policyData.mInitBundle.saveToXml(out);
+ out.endTag(null, TAG_INITIALIZATION_BUNDLE);
+ }
+
+ if (policyData.mPasswordTokenHandle != 0) {
+ out.startTag(null, TAG_PASSWORD_TOKEN_HANDLE);
+ out.attribute(null, ATTR_VALUE,
+ Long.toString(policyData.mPasswordTokenHandle));
+ out.endTag(null, TAG_PASSWORD_TOKEN_HANDLE);
+ }
+
+ if (policyData.mCurrentInputMethodSet) {
+ out.startTag(null, TAG_CURRENT_INPUT_METHOD_SET);
+ out.endTag(null, TAG_CURRENT_INPUT_METHOD_SET);
+ }
+
+ for (final String cert : policyData.mOwnerInstalledCaCerts) {
+ out.startTag(null, TAG_OWNER_INSTALLED_CA_CERT);
+ out.attribute(null, ATTR_ALIAS, cert);
+ out.endTag(null, TAG_OWNER_INSTALLED_CA_CERT);
+ }
+
+ for (int i = 0, size = policyData.mUserControlDisabledPackages.size(); i < size; i++) {
+ String packageName = policyData.mUserControlDisabledPackages.get(i);
+ out.startTag(null, TAG_PROTECTED_PACKAGES);
+ out.attribute(null, ATTR_NAME, packageName);
+ out.endTag(null, TAG_PROTECTED_PACKAGES);
+ }
+
+ if (policyData.mAppsSuspended) {
+ out.startTag(null, TAG_APPS_SUSPENDED);
+ out.attribute(null, ATTR_VALUE, Boolean.toString(policyData.mAppsSuspended));
+ out.endTag(null, TAG_APPS_SUSPENDED);
+ }
+
+ out.endTag(null, "policies");
+
+ out.endDocument();
+ stream.flush();
+ FileUtils.sync(stream);
+ stream.close();
+ file.commit();
+ return true;
+ } catch (XmlPullParserException | IOException e) {
+ Slog.w(DevicePolicyManagerService.LOG_TAG, "failed writing file", e);
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException ex) {
+ // Ignore
+ }
+ file.rollback();
+ return false;
+ }
+ }
+
+ /**
+ * @param adminInfoSupplier function that queries DeviceAdminInfo from PackageManager
+ * @param ownerComponent device or profile owner component if any.
+ */
+ static boolean load(DevicePolicyData policy, boolean isFdeDevice, JournaledFile journaledFile,
+ Function<ComponentName, DeviceAdminInfo> adminInfoSupplier,
+ ComponentName ownerComponent) {
+ FileInputStream stream = null;
+ File file = journaledFile.chooseForRead();
+ boolean needsRewrite = false;
+ try {
+ stream = new FileInputStream(file);
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(stream, StandardCharsets.UTF_8.name());
+
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && type != XmlPullParser.START_TAG) {
+ }
+ String tag = parser.getName();
+ if (!"policies".equals(tag)) {
+ throw new XmlPullParserException(
+ "Settings do not start with policies tag: found " + tag);
+ }
+
+ // Extract the permission provider component name if available
+ String permissionProvider = parser.getAttributeValue(null, ATTR_PERMISSION_PROVIDER);
+ if (permissionProvider != null) {
+ policy.mRestrictionsProvider =
+ ComponentName.unflattenFromString(permissionProvider);
+ }
+ String userSetupComplete = parser.getAttributeValue(null, ATTR_SETUP_COMPLETE);
+ if (Boolean.toString(true).equals(userSetupComplete)) {
+ policy.mUserSetupComplete = true;
+ }
+ String paired = parser.getAttributeValue(null, ATTR_DEVICE_PAIRED);
+ if (Boolean.toString(true).equals(paired)) {
+ policy.mPaired = true;
+ }
+ String deviceProvisioningConfigApplied = parser.getAttributeValue(null,
+ ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED);
+ if (Boolean.toString(true).equals(deviceProvisioningConfigApplied)) {
+ policy.mDeviceProvisioningConfigApplied = true;
+ }
+ String provisioningState = parser.getAttributeValue(null, ATTR_PROVISIONING_STATE);
+ if (!TextUtils.isEmpty(provisioningState)) {
+ policy.mUserProvisioningState = Integer.parseInt(provisioningState);
+ }
+ String permissionPolicy = parser.getAttributeValue(null, ATTR_PERMISSION_POLICY);
+ if (!TextUtils.isEmpty(permissionPolicy)) {
+ policy.mPermissionPolicy = Integer.parseInt(permissionPolicy);
+ }
+
+ parser.next();
+ int outerDepth = parser.getDepth();
+ policy.mLockTaskPackages.clear();
+ policy.mAdminList.clear();
+ policy.mAdminMap.clear();
+ policy.mAffiliationIds.clear();
+ policy.mOwnerInstalledCaCerts.clear();
+ policy.mUserControlDisabledPackages.clear();
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+ tag = parser.getName();
+ if ("admin".equals(tag)) {
+ String name = parser.getAttributeValue(null, "name");
+ try {
+ DeviceAdminInfo dai = adminInfoSupplier.apply(
+ ComponentName.unflattenFromString(name));
+
+ if (dai != null) {
+ // b/123415062: If DA, overwrite with the stored policies that were
+ // agreed by the user to prevent apps from sneaking additional policies
+ // into updates.
+ boolean overwritePolicies = !dai.getComponent().equals(ownerComponent);
+ ActiveAdmin ap = new ActiveAdmin(dai, /* parent */ false);
+ ap.readFromXml(parser, overwritePolicies);
+ policy.mAdminMap.put(ap.info.getComponent(), ap);
+ }
+ } catch (RuntimeException e) {
+ Slog.w(DevicePolicyManagerService.LOG_TAG,
+ "Failed loading admin " + name, e);
+ }
+ } else if ("delegation".equals(tag)) {
+ // Parse delegation info.
+ final String delegatePackage = parser.getAttributeValue(null,
+ "delegatePackage");
+ final String scope = parser.getAttributeValue(null, "scope");
+
+ // Get a reference to the scopes list for the delegatePackage.
+ List<String> scopes = policy.mDelegationMap.get(delegatePackage);
+ // Or make a new list if none was found.
+ if (scopes == null) {
+ scopes = new ArrayList<>();
+ policy.mDelegationMap.put(delegatePackage, scopes);
+ }
+ // Add the new scope to the list of delegatePackage if it's not already there.
+ if (!scopes.contains(scope)) {
+ scopes.add(scope);
+ }
+ } else if ("failed-password-attempts".equals(tag)) {
+ policy.mFailedPasswordAttempts = Integer.parseInt(
+ parser.getAttributeValue(null, "value"));
+ } else if ("password-owner".equals(tag)) {
+ policy.mPasswordOwner = Integer.parseInt(
+ parser.getAttributeValue(null, "value"));
+ } else if (TAG_ACCEPTED_CA_CERTIFICATES.equals(tag)) {
+ policy.mAcceptedCaCertificates.add(parser.getAttributeValue(null, ATTR_NAME));
+ } else if (TAG_LOCK_TASK_COMPONENTS.equals(tag)) {
+ policy.mLockTaskPackages.add(parser.getAttributeValue(null, "name"));
+ } else if (TAG_LOCK_TASK_FEATURES.equals(tag)) {
+ policy.mLockTaskFeatures = Integer.parseInt(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_SECONDARY_LOCK_SCREEN.equals(tag)) {
+ policy.mSecondaryLockscreenEnabled = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_STATUS_BAR.equals(tag)) {
+ policy.mStatusBarDisabled = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_DISABLED));
+ } else if (TAG_DO_NOT_ASK_CREDENTIALS_ON_BOOT.equals(tag)) {
+ policy.mDoNotAskCredentialsOnBoot = true;
+ } else if (TAG_AFFILIATION_ID.equals(tag)) {
+ policy.mAffiliationIds.add(parser.getAttributeValue(null, ATTR_ID));
+ } else if (TAG_LAST_SECURITY_LOG_RETRIEVAL.equals(tag)) {
+ policy.mLastSecurityLogRetrievalTime = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_LAST_BUG_REPORT_REQUEST.equals(tag)) {
+ policy.mLastBugReportRequestTime = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_LAST_NETWORK_LOG_RETRIEVAL.equals(tag)) {
+ policy.mLastNetworkLogsRetrievalTime = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_ADMIN_BROADCAST_PENDING.equals(tag)) {
+ String pending = parser.getAttributeValue(null, ATTR_VALUE);
+ policy.mAdminBroadcastPending = Boolean.toString(true).equals(pending);
+ } else if (TAG_INITIALIZATION_BUNDLE.equals(tag)) {
+ policy.mInitBundle = PersistableBundle.restoreFromXml(parser);
+ } else if ("active-password".equals(tag)) {
+ // Remove password metrics from saved settings, as we no longer wish to store
+ // these on disk
+ needsRewrite = true;
+ } else if (TAG_PASSWORD_VALIDITY.equals(tag)) {
+ if (isFdeDevice) {
+ // This flag is only used for FDE devices
+ policy.mPasswordValidAtLastCheckpoint = Boolean.parseBoolean(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ }
+ } else if (TAG_PASSWORD_TOKEN_HANDLE.equals(tag)) {
+ policy.mPasswordTokenHandle = Long.parseLong(
+ parser.getAttributeValue(null, ATTR_VALUE));
+ } else if (TAG_CURRENT_INPUT_METHOD_SET.equals(tag)) {
+ policy.mCurrentInputMethodSet = true;
+ } else if (TAG_OWNER_INSTALLED_CA_CERT.equals(tag)) {
+ policy.mOwnerInstalledCaCerts.add(parser.getAttributeValue(null, ATTR_ALIAS));
+ } else if (TAG_PROTECTED_PACKAGES.equals(tag)) {
+ policy.mUserControlDisabledPackages.add(
+ parser.getAttributeValue(null, ATTR_NAME));
+ } else if (TAG_APPS_SUSPENDED.equals(tag)) {
+ policy.mAppsSuspended =
+ Boolean.parseBoolean(parser.getAttributeValue(null, ATTR_VALUE));
+ } else {
+ Slog.w(DevicePolicyManagerService.LOG_TAG, "Unknown tag: " + tag);
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+ } catch (FileNotFoundException e) {
+ // Don't be noisy, this is normal if we haven't defined any policies.
+ } catch (NullPointerException | NumberFormatException | XmlPullParserException | IOException
+ | IndexOutOfBoundsException e) {
+ Slog.w(DevicePolicyManagerService.LOG_TAG, "failed parsing " + file, e);
+ }
+ try {
+ if (stream != null) {
+ stream.close();
+ }
+ } catch (IOException e) {
+ // Ignore
+ }
+
+ // Generate a list of admins from the admin map
+ policy.mAdminList.addAll(policy.mAdminMap.values());
+ return needsRewrite;
+ }
+
+ void validatePasswordOwner() {
+ if (mPasswordOwner >= 0) {
+ boolean haveOwner = false;
+ for (int i = mAdminList.size() - 1; i >= 0; i--) {
+ if (mAdminList.get(i).getUid() == mPasswordOwner) {
+ haveOwner = true;
+ break;
+ }
+ }
+ if (!haveOwner) {
+ Slog.w(DevicePolicyManagerService.LOG_TAG, "Previous password owner "
+ + mPasswordOwner + " no longer active; disabling");
+ mPasswordOwner = -1;
+ }
+ }
+ }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9a2bef85860f..cafd56e5198b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -106,10 +106,6 @@ import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.A
import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.ADMIN_TYPE_PROFILE_OWNER;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
-import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
-import static org.xmlpull.v1.XmlPullParser.END_TAG;
-import static org.xmlpull.v1.XmlPullParser.TEXT;
-
import android.Manifest.permission;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accounts.Account;
@@ -189,7 +185,6 @@ import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.Cursor;
import android.graphics.Bitmap;
-import android.graphics.Color;
import android.location.LocationManager;
import android.media.AudioManager;
import android.media.IAudioService;
@@ -204,7 +199,6 @@ import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
-import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -248,7 +242,6 @@ import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.text.TextUtils;
import android.text.format.DateUtils;
-import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Log;
@@ -280,7 +273,6 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.JournaledFile;
import com.android.internal.util.Preconditions;
import com.android.internal.util.StatLogger;
-import com.android.internal.util.XmlUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockSettingsInternal;
import com.android.internal.widget.LockscreenCredential;
@@ -290,8 +282,7 @@ import com.android.server.LockGuard;
import com.android.server.PersistentDataBlockManagerInternal;
import com.android.server.SystemServerInitThreadPool;
import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
-import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
+import com.android.server.devicepolicy.ActiveAdmin.TrustAgentInfo;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.server.pm.RestrictionsSet;
@@ -328,7 +319,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -350,55 +340,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private static final String TRANSFER_OWNERSHIP_PARAMETERS_XML =
"transfer-ownership-parameters.xml";
- private static final String TAG_ACCEPTED_CA_CERTIFICATES = "accepted-ca-certificate";
-
- private static final String TAG_LOCK_TASK_COMPONENTS = "lock-task-component";
-
- private static final String TAG_LOCK_TASK_FEATURES = "lock-task-features";
-
- private static final String TAG_STATUS_BAR = "statusbar";
-
- private static final String ATTR_DISABLED = "disabled";
-
- private static final String ATTR_NAME = "name";
-
- private static final String DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML =
- "do-not-ask-credentials-on-boot";
-
- private static final String TAG_AFFILIATION_ID = "affiliation-id";
-
- private static final String TAG_LAST_SECURITY_LOG_RETRIEVAL = "last-security-log-retrieval";
-
- private static final String TAG_LAST_BUG_REPORT_REQUEST = "last-bug-report-request";
-
- private static final String TAG_LAST_NETWORK_LOG_RETRIEVAL = "last-network-log-retrieval";
-
- private static final String TAG_ADMIN_BROADCAST_PENDING = "admin-broadcast-pending";
-
- private static final String TAG_CURRENT_INPUT_METHOD_SET = "current-ime-set";
-
- private static final String TAG_OWNER_INSTALLED_CA_CERT = "owner-installed-ca-cert";
-
- private static final String ATTR_ID = "id";
-
- private static final String ATTR_VALUE = "value";
-
- private static final String ATTR_ALIAS = "alias";
-
- private static final String TAG_INITIALIZATION_BUNDLE = "initialization-bundle";
-
- private static final String TAG_PASSWORD_TOKEN_HANDLE = "password-token";
-
- private static final String TAG_PASSWORD_VALIDITY = "password-validity";
-
private static final String TAG_TRANSFER_OWNERSHIP_BUNDLE = "transfer-ownership-bundle";
- private static final String TAG_PROTECTED_PACKAGES = "protected-packages";
-
- private static final String TAG_SECONDARY_LOCK_SCREEN = "secondary-lock-screen";
-
- private static final String TAG_APPS_SUSPENDED = "apps-suspended";
-
private static final int REQUEST_EXPIRE_PASSWORD = 5571;
private static final int REQUEST_PROFILE_OFF_DEADLINE = 5572;
@@ -423,17 +366,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
static final String ACTION_PROFILE_OFF_DEADLINE =
"com.android.server.ACTION_PROFILE_OFF_DEADLINE";
- private static final String ATTR_PERMISSION_PROVIDER = "permission-provider";
- private static final String ATTR_SETUP_COMPLETE = "setup-complete";
- private static final String ATTR_PROVISIONING_STATE = "provisioning-state";
- private static final String ATTR_PERMISSION_POLICY = "permission-policy";
- private static final String ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED =
- "device-provisioning-config-applied";
- private static final String ATTR_DEVICE_PAIRED = "device-paired";
- private static final String ATTR_DELEGATED_CERT_INSTALLER = "delegated-cert-installer";
- private static final String ATTR_APPLICATION_RESTRICTIONS_MANAGER
- = "application-restrictions-manager";
-
private static final String CALLED_FROM_PARENT = "calledFromParent";
private static final String NOT_CALLED_FROM_PARENT = "notCalledFromParent";
@@ -488,7 +420,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private static final Set<String> SYSTEM_SETTINGS_WHITELIST;
private static final Set<Integer> DA_DISALLOWED_POLICIES;
// A collection of user restrictions that are deprecated and should simply be ignored.
- private static final Set<String> DEPRECATED_USER_RESTRICTIONS;
private static final String AB_DEVICE_KEY = "ro.build.ab_update";
static {
@@ -532,10 +463,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD);
DA_DISALLOWED_POLICIES.add(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
-
- DEPRECATED_USER_RESTRICTIONS = Sets.newHashSet(
- UserManager.DISALLOW_ADD_MANAGED_PROFILE,
- UserManager.DISALLOW_REMOVE_MANAGED_PROFILE);
}
/**
@@ -791,76 +718,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
- public static class DevicePolicyData {
- int mFailedPasswordAttempts = 0;
- boolean mPasswordValidAtLastCheckpoint = true;
-
- int mUserHandle;
- int mPasswordOwner = -1;
- long mLastMaximumTimeToLock = -1;
- boolean mUserSetupComplete = false;
- boolean mPaired = false;
- int mUserProvisioningState;
- int mPermissionPolicy;
-
- boolean mDeviceProvisioningConfigApplied = false;
-
- final ArrayMap<ComponentName, ActiveAdmin> mAdminMap = new ArrayMap<>();
- final ArrayList<ActiveAdmin> mAdminList = new ArrayList<>();
- final ArrayList<ComponentName> mRemovingAdmins = new ArrayList<>();
-
- // TODO(b/35385311): Keep track of metadata in TrustedCertificateStore instead.
- final ArraySet<String> mAcceptedCaCertificates = new ArraySet<>();
-
- // This is the list of component allowed to start lock task mode.
- List<String> mLockTaskPackages = new ArrayList<>();
-
- // List of packages protected by device owner
- List<String> mUserControlDisabledPackages = new ArrayList<>();
-
- // Bitfield of feature flags to be enabled during LockTask mode.
- // We default on the power button menu, in order to be consistent with pre-P behaviour.
- int mLockTaskFeatures = DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS;
-
- boolean mStatusBarDisabled = false;
-
- ComponentName mRestrictionsProvider;
-
- // Map of delegate package to delegation scopes
- final ArrayMap<String, List<String>> mDelegationMap = new ArrayMap<>();
-
- boolean doNotAskCredentialsOnBoot = false;
-
- Set<String> mAffiliationIds = new ArraySet<>();
-
- long mLastSecurityLogRetrievalTime = -1;
-
- long mLastBugReportRequestTime = -1;
-
- long mLastNetworkLogsRetrievalTime = -1;
-
- boolean mCurrentInputMethodSet = false;
-
- boolean mSecondaryLockscreenEnabled = false;
-
- // TODO(b/35385311): Keep track of metadata in TrustedCertificateStore instead.
- Set<String> mOwnerInstalledCaCerts = new ArraySet<>();
-
- // Used for initialization of users created by createAndManageUser.
- boolean mAdminBroadcastPending = false;
- PersistableBundle mInitBundle = null;
-
- long mPasswordTokenHandle = 0;
-
- // Whether user's apps are suspended. This flag should only be written AFTER all the needed
- // apps were suspended or unsuspended.
- boolean mAppsSuspended = false;
-
- public DevicePolicyData(int userHandle) {
- mUserHandle = userHandle;
- }
- }
-
@GuardedBy("getLockObject()")
final SparseArray<DevicePolicyData> mUserData = new SparseArray<>();
@@ -1045,1002 +902,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
- static class ActiveAdmin {
- private static final String TAG_DISABLE_KEYGUARD_FEATURES = "disable-keyguard-features";
- private static final String TAG_TEST_ONLY_ADMIN = "test-only-admin";
- private static final String TAG_DISABLE_CAMERA = "disable-camera";
- private static final String TAG_DISABLE_CALLER_ID = "disable-caller-id";
- private static final String TAG_DISABLE_CONTACTS_SEARCH = "disable-contacts-search";
- private static final String TAG_DISABLE_BLUETOOTH_CONTACT_SHARING
- = "disable-bt-contacts-sharing";
- private static final String TAG_DISABLE_SCREEN_CAPTURE = "disable-screen-capture";
- private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management";
- private static final String TAG_REQUIRE_AUTO_TIME = "require_auto_time";
- private static final String TAG_FORCE_EPHEMERAL_USERS = "force_ephemeral_users";
- private static final String TAG_IS_NETWORK_LOGGING_ENABLED = "is_network_logging_enabled";
- private static final String TAG_ACCOUNT_TYPE = "account-type";
- private static final String TAG_PERMITTED_ACCESSIBILITY_SERVICES
- = "permitted-accessiblity-services";
- private static final String TAG_ENCRYPTION_REQUESTED = "encryption-requested";
- private static final String TAG_MANAGE_TRUST_AGENT_FEATURES = "manage-trust-agent-features";
- private static final String TAG_TRUST_AGENT_COMPONENT_OPTIONS = "trust-agent-component-options";
- private static final String TAG_TRUST_AGENT_COMPONENT = "component";
- private static final String TAG_PASSWORD_EXPIRATION_DATE = "password-expiration-date";
- private static final String TAG_PASSWORD_EXPIRATION_TIMEOUT = "password-expiration-timeout";
- private static final String TAG_GLOBAL_PROXY_EXCLUSION_LIST = "global-proxy-exclusion-list";
- private static final String TAG_GLOBAL_PROXY_SPEC = "global-proxy-spec";
- private static final String TAG_SPECIFIES_GLOBAL_PROXY = "specifies-global-proxy";
- private static final String TAG_PERMITTED_IMES = "permitted-imes";
- private static final String TAG_PERMITTED_NOTIFICATION_LISTENERS =
- "permitted-notification-listeners";
- private static final String TAG_MAX_FAILED_PASSWORD_WIPE = "max-failed-password-wipe";
- private static final String TAG_MAX_TIME_TO_UNLOCK = "max-time-to-unlock";
- private static final String TAG_STRONG_AUTH_UNLOCK_TIMEOUT = "strong-auth-unlock-timeout";
- private static final String TAG_MIN_PASSWORD_NONLETTER = "min-password-nonletter";
- private static final String TAG_MIN_PASSWORD_SYMBOLS = "min-password-symbols";
- private static final String TAG_MIN_PASSWORD_NUMERIC = "min-password-numeric";
- private static final String TAG_MIN_PASSWORD_LETTERS = "min-password-letters";
- private static final String TAG_MIN_PASSWORD_LOWERCASE = "min-password-lowercase";
- private static final String TAG_MIN_PASSWORD_UPPERCASE = "min-password-uppercase";
- private static final String TAG_PASSWORD_HISTORY_LENGTH = "password-history-length";
- private static final String TAG_MIN_PASSWORD_LENGTH = "min-password-length";
- private static final String ATTR_VALUE = "value";
- private static final String TAG_PASSWORD_QUALITY = "password-quality";
- private static final String TAG_POLICIES = "policies";
- private static final String TAG_CROSS_PROFILE_WIDGET_PROVIDERS =
- "cross-profile-widget-providers";
- private static final String TAG_PROVIDER = "provider";
- private static final String TAG_PACKAGE_LIST_ITEM = "item";
- private static final String TAG_KEEP_UNINSTALLED_PACKAGES = "keep-uninstalled-packages";
- private static final String TAG_USER_RESTRICTIONS = "user-restrictions";
- private static final String TAG_DEFAULT_ENABLED_USER_RESTRICTIONS =
- "default-enabled-user-restrictions";
- private static final String TAG_RESTRICTION = "restriction";
- private static final String TAG_SHORT_SUPPORT_MESSAGE = "short-support-message";
- private static final String TAG_LONG_SUPPORT_MESSAGE = "long-support-message";
- private static final String TAG_PARENT_ADMIN = "parent-admin";
- private static final String TAG_ORGANIZATION_COLOR = "organization-color";
- private static final String TAG_ORGANIZATION_NAME = "organization-name";
- private static final String ATTR_LAST_NETWORK_LOGGING_NOTIFICATION = "last-notification";
- private static final String ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS = "num-notifications";
- private static final String TAG_IS_LOGOUT_ENABLED = "is_logout_enabled";
- private static final String TAG_START_USER_SESSION_MESSAGE = "start_user_session_message";
- private static final String TAG_END_USER_SESSION_MESSAGE = "end_user_session_message";
- private static final String TAG_METERED_DATA_DISABLED_PACKAGES =
- "metered_data_disabled_packages";
- private static final String TAG_CROSS_PROFILE_CALENDAR_PACKAGES =
- "cross-profile-calendar-packages";
- private static final String TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL =
- "cross-profile-calendar-packages-null";
- private static final String TAG_CROSS_PROFILE_PACKAGES = "cross-profile-packages";
- private static final String TAG_FACTORY_RESET_PROTECTION_POLICY =
- "factory_reset_protection_policy";
- private static final String TAG_SUSPEND_PERSONAL_APPS = "suspend-personal-apps";
- private static final String TAG_PROFILE_MAXIMUM_TIME_OFF = "profile-max-time-off";
- private static final String TAG_PROFILE_OFF_DEADLINE = "profile-off-deadline";
- private static final String TAG_ALWAYS_ON_VPN_PACKAGE = "vpn-package";
- private static final String TAG_ALWAYS_ON_VPN_LOCKDOWN = "vpn-lockdown";
- private static final String TAG_COMMON_CRITERIA_MODE = "common-criteria-mode";
- DeviceAdminInfo info;
-
-
- static final int DEF_PASSWORD_HISTORY_LENGTH = 0;
- int passwordHistoryLength = DEF_PASSWORD_HISTORY_LENGTH;
-
- @NonNull
- PasswordPolicy mPasswordPolicy = new PasswordPolicy();
-
- @Nullable
- FactoryResetProtectionPolicy mFactoryResetProtectionPolicy = null;
-
- static final long DEF_MAXIMUM_TIME_TO_UNLOCK = 0;
- long maximumTimeToUnlock = DEF_MAXIMUM_TIME_TO_UNLOCK;
-
- long strongAuthUnlockTimeout = 0; // admin doesn't participate by default
-
- static final int DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE = 0;
- int maximumFailedPasswordsForWipe = DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE;
-
- static final long DEF_PASSWORD_EXPIRATION_TIMEOUT = 0;
- long passwordExpirationTimeout = DEF_PASSWORD_EXPIRATION_TIMEOUT;
-
- static final long DEF_PASSWORD_EXPIRATION_DATE = 0;
- long passwordExpirationDate = DEF_PASSWORD_EXPIRATION_DATE;
-
- static final int DEF_KEYGUARD_FEATURES_DISABLED = 0; // none
-
- int disabledKeyguardFeatures = DEF_KEYGUARD_FEATURES_DISABLED;
-
- boolean encryptionRequested = false;
- boolean testOnlyAdmin = false;
- boolean disableCamera = false;
- boolean disableCallerId = false;
- boolean disableContactsSearch = false;
- boolean disableBluetoothContactSharing = true;
- boolean disableScreenCapture = false; // Can only be set by a device/profile owner.
- boolean requireAutoTime = false; // Can only be set by a device owner.
- boolean forceEphemeralUsers = false; // Can only be set by a device owner.
- boolean isNetworkLoggingEnabled = false; // Can only be set by a device owner.
- boolean isLogoutEnabled = false; // Can only be set by a device owner.
-
- // one notification after enabling + one more after reboots
- static final int DEF_MAXIMUM_NETWORK_LOGGING_NOTIFICATIONS_SHOWN = 2;
- int numNetworkLoggingNotifications = 0;
- long lastNetworkLoggingNotificationTimeMs = 0; // Time in milliseconds since epoch
-
- ActiveAdmin parentAdmin;
- final boolean isParent;
-
- static class TrustAgentInfo {
- public PersistableBundle options;
- TrustAgentInfo(PersistableBundle bundle) {
- options = bundle;
- }
- }
-
- // The list of packages which are not allowed to use metered data.
- List<String> meteredDisabledPackages;
-
- final Set<String> accountTypesWithManagementDisabled = new ArraySet<>();
-
- // The list of permitted accessibility services package namesas set by a profile
- // or device owner. Null means all accessibility services are allowed, empty means
- // none except system services are allowed.
- List<String> permittedAccessiblityServices;
-
- // The list of permitted input methods package names as set by a profile or device owner.
- // Null means all input methods are allowed, empty means none except system imes are
- // allowed.
- List<String> permittedInputMethods;
-
- // The list of packages allowed to use a NotificationListenerService to receive events for
- // notifications from this user. Null means that all packages are allowed. Empty list means
- // that only packages from the system are allowed.
- List<String> permittedNotificationListeners;
-
- // List of package names to keep cached.
- List<String> keepUninstalledPackages;
-
- // TODO: review implementation decisions with frameworks team
- boolean specifiesGlobalProxy = false;
- String globalProxySpec = null;
- String globalProxyExclusionList = null;
-
- @NonNull ArrayMap<String, TrustAgentInfo> trustAgentInfos = new ArrayMap<>();
-
- List<String> crossProfileWidgetProviders;
-
- Bundle userRestrictions;
-
- // User restrictions that have already been enabled by default for this admin (either when
- // setting the device or profile owner, or during a system update if one of those "enabled
- // by default" restrictions is newly added).
- final Set<String> defaultEnabledRestrictionsAlreadySet = new ArraySet<>();
-
- // Support text provided by the admin to display to the user.
- CharSequence shortSupportMessage = null;
- CharSequence longSupportMessage = null;
-
- // Background color of confirm credentials screen. Default: teal.
- static final int DEF_ORGANIZATION_COLOR = Color.parseColor("#00796B");
- int organizationColor = DEF_ORGANIZATION_COLOR;
-
- // Default title of confirm credentials screen
- String organizationName = null;
-
- // Message for user switcher
- String startUserSessionMessage = null;
- String endUserSessionMessage = null;
-
- // The whitelist of packages that can access cross profile calendar APIs.
- // This whitelist should be in default an empty list, which indicates that no package
- // is whitelisted.
- List<String> mCrossProfileCalendarPackages = Collections.emptyList();
-
- // The whitelist of packages that the admin has enabled to be able to request consent from
- // the user to communicate cross-profile. By default, no packages are whitelisted, which is
- // represented as an empty list.
- List<String> mCrossProfilePackages = Collections.emptyList();
-
- // Whether the admin explicitly requires personal apps to be suspended
- boolean mSuspendPersonalApps = false;
- // Maximum time the profile owned by this admin can be off.
- long mProfileMaximumTimeOffMillis = 0;
- // Time by which the profile should be turned on according to System.currentTimeMillis().
- long mProfileOffDeadline = 0;
-
- public String mAlwaysOnVpnPackage;
- public boolean mAlwaysOnVpnLockdown;
- boolean mCommonCriteriaMode;
-
- ActiveAdmin(DeviceAdminInfo _info, boolean parent) {
- info = _info;
- isParent = parent;
- }
-
- ActiveAdmin getParentActiveAdmin() {
- Preconditions.checkState(!isParent);
-
- if (parentAdmin == null) {
- parentAdmin = new ActiveAdmin(info, /* parent */ true);
- }
- return parentAdmin;
- }
-
- boolean hasParentActiveAdmin() {
- return parentAdmin != null;
- }
-
- int getUid() { return info.getActivityInfo().applicationInfo.uid; }
-
- public UserHandle getUserHandle() {
- return UserHandle.of(UserHandle.getUserId(info.getActivityInfo().applicationInfo.uid));
- }
-
- void writeToXml(XmlSerializer out)
- throws IllegalArgumentException, IllegalStateException, IOException {
- out.startTag(null, TAG_POLICIES);
- info.writePoliciesToXml(out);
- out.endTag(null, TAG_POLICIES);
- if (mPasswordPolicy.quality != PASSWORD_QUALITY_UNSPECIFIED) {
- writeAttributeValueToXml(
- out, TAG_PASSWORD_QUALITY, mPasswordPolicy.quality);
- if (mPasswordPolicy.length != PasswordPolicy.DEF_MINIMUM_LENGTH) {
- writeAttributeValueToXml(
- out, TAG_MIN_PASSWORD_LENGTH, mPasswordPolicy.length);
- }
- if (mPasswordPolicy.upperCase != PasswordPolicy.DEF_MINIMUM_UPPER_CASE) {
- writeAttributeValueToXml(
- out, TAG_MIN_PASSWORD_UPPERCASE, mPasswordPolicy.upperCase);
- }
- if (mPasswordPolicy.lowerCase != PasswordPolicy.DEF_MINIMUM_LOWER_CASE) {
- writeAttributeValueToXml(
- out, TAG_MIN_PASSWORD_LOWERCASE, mPasswordPolicy.lowerCase);
- }
- if (mPasswordPolicy.letters != PasswordPolicy.DEF_MINIMUM_LETTERS) {
- writeAttributeValueToXml(
- out, TAG_MIN_PASSWORD_LETTERS, mPasswordPolicy.letters);
- }
- if (mPasswordPolicy.numeric != PasswordPolicy.DEF_MINIMUM_NUMERIC) {
- writeAttributeValueToXml(
- out, TAG_MIN_PASSWORD_NUMERIC, mPasswordPolicy.numeric);
- }
- if (mPasswordPolicy.symbols != PasswordPolicy.DEF_MINIMUM_SYMBOLS) {
- writeAttributeValueToXml(
- out, TAG_MIN_PASSWORD_SYMBOLS, mPasswordPolicy.symbols);
- }
- if (mPasswordPolicy.nonLetter > PasswordPolicy.DEF_MINIMUM_NON_LETTER) {
- writeAttributeValueToXml(
- out, TAG_MIN_PASSWORD_NONLETTER, mPasswordPolicy.nonLetter);
- }
- }
- if (passwordHistoryLength != DEF_PASSWORD_HISTORY_LENGTH) {
- writeAttributeValueToXml(
- out, TAG_PASSWORD_HISTORY_LENGTH, passwordHistoryLength);
- }
- if (maximumTimeToUnlock != DEF_MAXIMUM_TIME_TO_UNLOCK) {
- writeAttributeValueToXml(
- out, TAG_MAX_TIME_TO_UNLOCK, maximumTimeToUnlock);
- }
- if (strongAuthUnlockTimeout != DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS) {
- writeAttributeValueToXml(
- out, TAG_STRONG_AUTH_UNLOCK_TIMEOUT, strongAuthUnlockTimeout);
- }
- if (maximumFailedPasswordsForWipe != DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) {
- writeAttributeValueToXml(
- out, TAG_MAX_FAILED_PASSWORD_WIPE, maximumFailedPasswordsForWipe);
- }
- if (specifiesGlobalProxy) {
- writeAttributeValueToXml(
- out, TAG_SPECIFIES_GLOBAL_PROXY, specifiesGlobalProxy);
- if (globalProxySpec != null) {
- writeAttributeValueToXml(out, TAG_GLOBAL_PROXY_SPEC, globalProxySpec);
- }
- if (globalProxyExclusionList != null) {
- writeAttributeValueToXml(
- out, TAG_GLOBAL_PROXY_EXCLUSION_LIST, globalProxyExclusionList);
- }
- }
- if (passwordExpirationTimeout != DEF_PASSWORD_EXPIRATION_TIMEOUT) {
- writeAttributeValueToXml(
- out, TAG_PASSWORD_EXPIRATION_TIMEOUT, passwordExpirationTimeout);
- }
- if (passwordExpirationDate != DEF_PASSWORD_EXPIRATION_DATE) {
- writeAttributeValueToXml(
- out, TAG_PASSWORD_EXPIRATION_DATE, passwordExpirationDate);
- }
- if (encryptionRequested) {
- writeAttributeValueToXml(
- out, TAG_ENCRYPTION_REQUESTED, encryptionRequested);
- }
- if (testOnlyAdmin) {
- writeAttributeValueToXml(
- out, TAG_TEST_ONLY_ADMIN, testOnlyAdmin);
- }
- if (disableCamera) {
- writeAttributeValueToXml(
- out, TAG_DISABLE_CAMERA, disableCamera);
- }
- if (disableCallerId) {
- writeAttributeValueToXml(
- out, TAG_DISABLE_CALLER_ID, disableCallerId);
- }
- if (disableContactsSearch) {
- writeAttributeValueToXml(
- out, TAG_DISABLE_CONTACTS_SEARCH, disableContactsSearch);
- }
- if (!disableBluetoothContactSharing) {
- writeAttributeValueToXml(
- out, TAG_DISABLE_BLUETOOTH_CONTACT_SHARING, disableBluetoothContactSharing);
- }
- if (disableScreenCapture) {
- writeAttributeValueToXml(
- out, TAG_DISABLE_SCREEN_CAPTURE, disableScreenCapture);
- }
- if (requireAutoTime) {
- writeAttributeValueToXml(
- out, TAG_REQUIRE_AUTO_TIME, requireAutoTime);
- }
- if (forceEphemeralUsers) {
- writeAttributeValueToXml(
- out, TAG_FORCE_EPHEMERAL_USERS, forceEphemeralUsers);
- }
- if (isNetworkLoggingEnabled) {
- out.startTag(null, TAG_IS_NETWORK_LOGGING_ENABLED);
- out.attribute(null, ATTR_VALUE, Boolean.toString(isNetworkLoggingEnabled));
- out.attribute(null, ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS,
- Integer.toString(numNetworkLoggingNotifications));
- out.attribute(null, ATTR_LAST_NETWORK_LOGGING_NOTIFICATION,
- Long.toString(lastNetworkLoggingNotificationTimeMs));
- out.endTag(null, TAG_IS_NETWORK_LOGGING_ENABLED);
- }
- if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) {
- writeAttributeValueToXml(
- out, TAG_DISABLE_KEYGUARD_FEATURES, disabledKeyguardFeatures);
- }
- if (!accountTypesWithManagementDisabled.isEmpty()) {
- writeAttributeValuesToXml(
- out, TAG_DISABLE_ACCOUNT_MANAGEMENT, TAG_ACCOUNT_TYPE,
- accountTypesWithManagementDisabled);
- }
- if (!trustAgentInfos.isEmpty()) {
- Set<Entry<String, TrustAgentInfo>> set = trustAgentInfos.entrySet();
- out.startTag(null, TAG_MANAGE_TRUST_AGENT_FEATURES);
- for (Entry<String, TrustAgentInfo> entry : set) {
- TrustAgentInfo trustAgentInfo = entry.getValue();
- out.startTag(null, TAG_TRUST_AGENT_COMPONENT);
- out.attribute(null, ATTR_VALUE, entry.getKey());
- if (trustAgentInfo.options != null) {
- out.startTag(null, TAG_TRUST_AGENT_COMPONENT_OPTIONS);
- try {
- trustAgentInfo.options.saveToXml(out);
- } catch (XmlPullParserException e) {
- Log.e(LOG_TAG, "Failed to save TrustAgent options", e);
- }
- out.endTag(null, TAG_TRUST_AGENT_COMPONENT_OPTIONS);
- }
- out.endTag(null, TAG_TRUST_AGENT_COMPONENT);
- }
- out.endTag(null, TAG_MANAGE_TRUST_AGENT_FEATURES);
- }
- if (crossProfileWidgetProviders != null && !crossProfileWidgetProviders.isEmpty()) {
- writeAttributeValuesToXml(
- out, TAG_CROSS_PROFILE_WIDGET_PROVIDERS, TAG_PROVIDER,
- crossProfileWidgetProviders);
- }
- writePackageListToXml(out, TAG_PERMITTED_ACCESSIBILITY_SERVICES,
- permittedAccessiblityServices);
- writePackageListToXml(out, TAG_PERMITTED_IMES, permittedInputMethods);
- writePackageListToXml(out, TAG_PERMITTED_NOTIFICATION_LISTENERS,
- permittedNotificationListeners);
- writePackageListToXml(out, TAG_KEEP_UNINSTALLED_PACKAGES, keepUninstalledPackages);
- writePackageListToXml(out, TAG_METERED_DATA_DISABLED_PACKAGES, meteredDisabledPackages);
- if (hasUserRestrictions()) {
- UserRestrictionsUtils.writeRestrictions(
- out, userRestrictions, TAG_USER_RESTRICTIONS);
- }
- if (!defaultEnabledRestrictionsAlreadySet.isEmpty()) {
- writeAttributeValuesToXml(out, TAG_DEFAULT_ENABLED_USER_RESTRICTIONS,
- TAG_RESTRICTION,
- defaultEnabledRestrictionsAlreadySet);
- }
- if (!TextUtils.isEmpty(shortSupportMessage)) {
- writeTextToXml(out, TAG_SHORT_SUPPORT_MESSAGE, shortSupportMessage.toString());
- }
- if (!TextUtils.isEmpty(longSupportMessage)) {
- writeTextToXml(out, TAG_LONG_SUPPORT_MESSAGE, longSupportMessage.toString());
- }
- if (parentAdmin != null) {
- out.startTag(null, TAG_PARENT_ADMIN);
- parentAdmin.writeToXml(out);
- out.endTag(null, TAG_PARENT_ADMIN);
- }
- if (organizationColor != DEF_ORGANIZATION_COLOR) {
- writeAttributeValueToXml(out, TAG_ORGANIZATION_COLOR, organizationColor);
- }
- if (organizationName != null) {
- writeTextToXml(out, TAG_ORGANIZATION_NAME, organizationName);
- }
- if (isLogoutEnabled) {
- writeAttributeValueToXml(out, TAG_IS_LOGOUT_ENABLED, isLogoutEnabled);
- }
- if (startUserSessionMessage != null) {
- writeTextToXml(out, TAG_START_USER_SESSION_MESSAGE, startUserSessionMessage);
- }
- if (endUserSessionMessage != null) {
- writeTextToXml(out, TAG_END_USER_SESSION_MESSAGE, endUserSessionMessage);
- }
- if (mCrossProfileCalendarPackages == null) {
- out.startTag(null, TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL);
- out.endTag(null, TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL);
- } else {
- writePackageListToXml(out, TAG_CROSS_PROFILE_CALENDAR_PACKAGES,
- mCrossProfileCalendarPackages);
- }
- writePackageListToXml(out, TAG_CROSS_PROFILE_PACKAGES, mCrossProfilePackages);
- if (mFactoryResetProtectionPolicy != null) {
- out.startTag(null, TAG_FACTORY_RESET_PROTECTION_POLICY);
- mFactoryResetProtectionPolicy.writeToXml(out);
- out.endTag(null, TAG_FACTORY_RESET_PROTECTION_POLICY);
- }
- if (mSuspendPersonalApps) {
- writeAttributeValueToXml(out, TAG_SUSPEND_PERSONAL_APPS, mSuspendPersonalApps);
- }
- if (mProfileMaximumTimeOffMillis != 0) {
- writeAttributeValueToXml(out, TAG_PROFILE_MAXIMUM_TIME_OFF,
- mProfileMaximumTimeOffMillis);
- }
- if (mProfileMaximumTimeOffMillis != 0) {
- writeAttributeValueToXml(out, TAG_PROFILE_OFF_DEADLINE, mProfileOffDeadline);
- }
- if (!TextUtils.isEmpty(mAlwaysOnVpnPackage)) {
- writeAttributeValueToXml(out, TAG_ALWAYS_ON_VPN_PACKAGE, mAlwaysOnVpnPackage);
- }
- if (mAlwaysOnVpnLockdown) {
- writeAttributeValueToXml(out, TAG_ALWAYS_ON_VPN_LOCKDOWN, mAlwaysOnVpnLockdown);
- }
- if (mCommonCriteriaMode) {
- writeAttributeValueToXml(out, TAG_COMMON_CRITERIA_MODE, mCommonCriteriaMode);
- }
- }
-
- void writeTextToXml(XmlSerializer out, String tag, String text) throws IOException {
- out.startTag(null, tag);
- out.text(text);
- out.endTag(null, tag);
- }
-
- void writePackageListToXml(XmlSerializer out, String outerTag,
- List<String> packageList)
- throws IllegalArgumentException, IllegalStateException, IOException {
- if (packageList == null) {
- return;
- }
- writeAttributeValuesToXml(out, outerTag, TAG_PACKAGE_LIST_ITEM, packageList);
- }
-
- void writeAttributeValueToXml(XmlSerializer out, String tag, String value)
- throws IOException {
- out.startTag(null, tag);
- out.attribute(null, ATTR_VALUE, value);
- out.endTag(null, tag);
- }
-
- void writeAttributeValueToXml(XmlSerializer out, String tag, int value)
- throws IOException {
- out.startTag(null, tag);
- out.attribute(null, ATTR_VALUE, Integer.toString(value));
- out.endTag(null, tag);
- }
-
- void writeAttributeValueToXml(XmlSerializer out, String tag, long value)
- throws IOException {
- out.startTag(null, tag);
- out.attribute(null, ATTR_VALUE, Long.toString(value));
- out.endTag(null, tag);
- }
-
- void writeAttributeValueToXml(XmlSerializer out, String tag, boolean value)
- throws IOException {
- out.startTag(null, tag);
- out.attribute(null, ATTR_VALUE, Boolean.toString(value));
- out.endTag(null, tag);
- }
-
- void writeAttributeValuesToXml(XmlSerializer out, String outerTag, String innerTag,
- @NonNull Collection<String> values) throws IOException {
- out.startTag(null, outerTag);
- for (String value : values) {
- out.startTag(null, innerTag);
- out.attribute(null, ATTR_VALUE, value);
- out.endTag(null, innerTag);
- }
- out.endTag(null, outerTag);
- }
-
- void readFromXml(XmlPullParser parser, boolean shouldOverridePolicies)
- throws XmlPullParserException, IOException {
- int outerDepth = parser.getDepth();
- int type;
- while ((type=parser.next()) != END_DOCUMENT
- && (type != END_TAG || parser.getDepth() > outerDepth)) {
- if (type == END_TAG || type == TEXT) {
- continue;
- }
- String tag = parser.getName();
- if (TAG_POLICIES.equals(tag)) {
- if (shouldOverridePolicies) {
- Log.d(LOG_TAG, "Overriding device admin policies from XML.");
- info.readPoliciesFromXml(parser);
- }
- } else if (TAG_PASSWORD_QUALITY.equals(tag)) {
- mPasswordPolicy.quality = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_MIN_PASSWORD_LENGTH.equals(tag)) {
- mPasswordPolicy.length = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_PASSWORD_HISTORY_LENGTH.equals(tag)) {
- passwordHistoryLength = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_MIN_PASSWORD_UPPERCASE.equals(tag)) {
- mPasswordPolicy.upperCase = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_MIN_PASSWORD_LOWERCASE.equals(tag)) {
- mPasswordPolicy.lowerCase = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_MIN_PASSWORD_LETTERS.equals(tag)) {
- mPasswordPolicy.letters = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_MIN_PASSWORD_NUMERIC.equals(tag)) {
- mPasswordPolicy.numeric = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_MIN_PASSWORD_SYMBOLS.equals(tag)) {
- mPasswordPolicy.symbols = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_MIN_PASSWORD_NONLETTER.equals(tag)) {
- mPasswordPolicy.nonLetter = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- }else if (TAG_MAX_TIME_TO_UNLOCK.equals(tag)) {
- maximumTimeToUnlock = Long.parseLong(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_STRONG_AUTH_UNLOCK_TIMEOUT.equals(tag)) {
- strongAuthUnlockTimeout = Long.parseLong(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_MAX_FAILED_PASSWORD_WIPE.equals(tag)) {
- maximumFailedPasswordsForWipe = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_SPECIFIES_GLOBAL_PROXY.equals(tag)) {
- specifiesGlobalProxy = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_GLOBAL_PROXY_SPEC.equals(tag)) {
- globalProxySpec =
- parser.getAttributeValue(null, ATTR_VALUE);
- } else if (TAG_GLOBAL_PROXY_EXCLUSION_LIST.equals(tag)) {
- globalProxyExclusionList =
- parser.getAttributeValue(null, ATTR_VALUE);
- } else if (TAG_PASSWORD_EXPIRATION_TIMEOUT.equals(tag)) {
- passwordExpirationTimeout = Long.parseLong(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_PASSWORD_EXPIRATION_DATE.equals(tag)) {
- passwordExpirationDate = Long.parseLong(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_ENCRYPTION_REQUESTED.equals(tag)) {
- encryptionRequested = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_TEST_ONLY_ADMIN.equals(tag)) {
- testOnlyAdmin = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_DISABLE_CAMERA.equals(tag)) {
- disableCamera = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_DISABLE_CALLER_ID.equals(tag)) {
- disableCallerId = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_DISABLE_CONTACTS_SEARCH.equals(tag)) {
- disableContactsSearch = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_DISABLE_BLUETOOTH_CONTACT_SHARING.equals(tag)) {
- disableBluetoothContactSharing = Boolean.parseBoolean(parser
- .getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_DISABLE_SCREEN_CAPTURE.equals(tag)) {
- disableScreenCapture = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_REQUIRE_AUTO_TIME.equals(tag)) {
- requireAutoTime = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_FORCE_EPHEMERAL_USERS.equals(tag)) {
- forceEphemeralUsers = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_IS_NETWORK_LOGGING_ENABLED.equals(tag)) {
- isNetworkLoggingEnabled = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- lastNetworkLoggingNotificationTimeMs = Long.parseLong(
- parser.getAttributeValue(null, ATTR_LAST_NETWORK_LOGGING_NOTIFICATION));
- numNetworkLoggingNotifications = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_NUM_NETWORK_LOGGING_NOTIFICATIONS));
- } else if (TAG_DISABLE_KEYGUARD_FEATURES.equals(tag)) {
- disabledKeyguardFeatures = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_DISABLE_ACCOUNT_MANAGEMENT.equals(tag)) {
- readAttributeValues(
- parser, TAG_ACCOUNT_TYPE, accountTypesWithManagementDisabled);
- } else if (TAG_MANAGE_TRUST_AGENT_FEATURES.equals(tag)) {
- trustAgentInfos = getAllTrustAgentInfos(parser, tag);
- } else if (TAG_CROSS_PROFILE_WIDGET_PROVIDERS.equals(tag)) {
- crossProfileWidgetProviders = new ArrayList<>();
- readAttributeValues(parser, TAG_PROVIDER, crossProfileWidgetProviders);
- } else if (TAG_PERMITTED_ACCESSIBILITY_SERVICES.equals(tag)) {
- permittedAccessiblityServices = readPackageList(parser, tag);
- } else if (TAG_PERMITTED_IMES.equals(tag)) {
- permittedInputMethods = readPackageList(parser, tag);
- } else if (TAG_PERMITTED_NOTIFICATION_LISTENERS.equals(tag)) {
- permittedNotificationListeners = readPackageList(parser, tag);
- } else if (TAG_KEEP_UNINSTALLED_PACKAGES.equals(tag)) {
- keepUninstalledPackages = readPackageList(parser, tag);
- } else if (TAG_METERED_DATA_DISABLED_PACKAGES.equals(tag)) {
- meteredDisabledPackages = readPackageList(parser, tag);
- } else if (TAG_USER_RESTRICTIONS.equals(tag)) {
- userRestrictions = UserRestrictionsUtils.readRestrictions(parser);
- } else if (TAG_DEFAULT_ENABLED_USER_RESTRICTIONS.equals(tag)) {
- readAttributeValues(
- parser, TAG_RESTRICTION, defaultEnabledRestrictionsAlreadySet);
- } else if (TAG_SHORT_SUPPORT_MESSAGE.equals(tag)) {
- type = parser.next();
- if (type == XmlPullParser.TEXT) {
- shortSupportMessage = parser.getText();
- } else {
- Log.w(LOG_TAG, "Missing text when loading short support message");
- }
- } else if (TAG_LONG_SUPPORT_MESSAGE.equals(tag)) {
- type = parser.next();
- if (type == XmlPullParser.TEXT) {
- longSupportMessage = parser.getText();
- } else {
- Log.w(LOG_TAG, "Missing text when loading long support message");
- }
- } else if (TAG_PARENT_ADMIN.equals(tag)) {
- Preconditions.checkState(!isParent);
- parentAdmin = new ActiveAdmin(info, /* parent */ true);
- parentAdmin.readFromXml(parser, shouldOverridePolicies);
- } else if (TAG_ORGANIZATION_COLOR.equals(tag)) {
- organizationColor = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_ORGANIZATION_NAME.equals(tag)) {
- type = parser.next();
- if (type == XmlPullParser.TEXT) {
- organizationName = parser.getText();
- } else {
- Log.w(LOG_TAG, "Missing text when loading organization name");
- }
- } else if (TAG_IS_LOGOUT_ENABLED.equals(tag)) {
- isLogoutEnabled = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_START_USER_SESSION_MESSAGE.equals(tag)) {
- type = parser.next();
- if (type == XmlPullParser.TEXT) {
- startUserSessionMessage = parser.getText();
- } else {
- Log.w(LOG_TAG, "Missing text when loading start session message");
- }
- } else if (TAG_END_USER_SESSION_MESSAGE.equals(tag)) {
- type = parser.next();
- if (type == XmlPullParser.TEXT) {
- endUserSessionMessage = parser.getText();
- } else {
- Log.w(LOG_TAG, "Missing text when loading end session message");
- }
- } else if (TAG_CROSS_PROFILE_CALENDAR_PACKAGES.equals(tag)) {
- mCrossProfileCalendarPackages = readPackageList(parser, tag);
- } else if (TAG_CROSS_PROFILE_CALENDAR_PACKAGES_NULL.equals(tag)) {
- mCrossProfileCalendarPackages = null;
- } else if (TAG_CROSS_PROFILE_PACKAGES.equals(tag)) {
- mCrossProfilePackages = readPackageList(parser, tag);
- } else if (TAG_FACTORY_RESET_PROTECTION_POLICY.equals(tag)) {
- mFactoryResetProtectionPolicy = FactoryResetProtectionPolicy.readFromXml(
- parser);
- } else if (TAG_SUSPEND_PERSONAL_APPS.equals(tag)) {
- mSuspendPersonalApps = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_PROFILE_MAXIMUM_TIME_OFF.equals(tag)) {
- mProfileMaximumTimeOffMillis =
- Long.parseLong(parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_PROFILE_OFF_DEADLINE.equals(tag)) {
- mProfileOffDeadline =
- Long.parseLong(parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_ALWAYS_ON_VPN_PACKAGE.equals(tag)) {
- mAlwaysOnVpnPackage = parser.getAttributeValue(null, ATTR_VALUE);
- } else if (TAG_ALWAYS_ON_VPN_LOCKDOWN.equals(tag)) {
- mAlwaysOnVpnLockdown = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_COMMON_CRITERIA_MODE.equals(tag)) {
- mCommonCriteriaMode = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else {
- Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
- XmlUtils.skipCurrentTag(parser);
- }
- }
- }
-
- private List<String> readPackageList(XmlPullParser parser,
- String tag) throws XmlPullParserException, IOException {
- List<String> result = new ArrayList<String>();
- int outerDepth = parser.getDepth();
- int outerType;
- while ((outerType=parser.next()) != XmlPullParser.END_DOCUMENT
- && (outerType != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (outerType == XmlPullParser.END_TAG || outerType == XmlPullParser.TEXT) {
- continue;
- }
- String outerTag = parser.getName();
- if (TAG_PACKAGE_LIST_ITEM.equals(outerTag)) {
- String packageName = parser.getAttributeValue(null, ATTR_VALUE);
- if (packageName != null) {
- result.add(packageName);
- } else {
- Slog.w(LOG_TAG, "Package name missing under " + outerTag);
- }
- } else {
- Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + outerTag);
- }
- }
- return result;
- }
-
- private void readAttributeValues(
- XmlPullParser parser, String tag, Collection<String> result)
- throws XmlPullParserException, IOException {
- result.clear();
- int outerDepthDAM = parser.getDepth();
- int typeDAM;
- while ((typeDAM=parser.next()) != END_DOCUMENT
- && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
- if (typeDAM == END_TAG || typeDAM == TEXT) {
- continue;
- }
- String tagDAM = parser.getName();
- if (tag.equals(tagDAM)) {
- result.add(parser.getAttributeValue(null, ATTR_VALUE));
- } else {
- Slog.e(LOG_TAG, "Expected tag " + tag + " but found " + tagDAM);
- }
- }
- }
-
- @NonNull
- private ArrayMap<String, TrustAgentInfo> getAllTrustAgentInfos(
- XmlPullParser parser, String tag) throws XmlPullParserException, IOException {
- int outerDepthDAM = parser.getDepth();
- int typeDAM;
- final ArrayMap<String, TrustAgentInfo> result = new ArrayMap<>();
- while ((typeDAM=parser.next()) != END_DOCUMENT
- && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
- if (typeDAM == END_TAG || typeDAM == TEXT) {
- continue;
- }
- String tagDAM = parser.getName();
- if (TAG_TRUST_AGENT_COMPONENT.equals(tagDAM)) {
- final String component = parser.getAttributeValue(null, ATTR_VALUE);
- final TrustAgentInfo trustAgentInfo = getTrustAgentInfo(parser, tag);
- result.put(component, trustAgentInfo);
- } else {
- Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
- }
- }
- return result;
- }
-
- private TrustAgentInfo getTrustAgentInfo(XmlPullParser parser, String tag)
- throws XmlPullParserException, IOException {
- int outerDepthDAM = parser.getDepth();
- int typeDAM;
- TrustAgentInfo result = new TrustAgentInfo(null);
- while ((typeDAM=parser.next()) != END_DOCUMENT
- && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
- if (typeDAM == END_TAG || typeDAM == TEXT) {
- continue;
- }
- String tagDAM = parser.getName();
- if (TAG_TRUST_AGENT_COMPONENT_OPTIONS.equals(tagDAM)) {
- result.options = PersistableBundle.restoreFromXml(parser);
- } else {
- Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
- }
- }
- return result;
- }
-
- boolean hasUserRestrictions() {
- return userRestrictions != null && userRestrictions.size() > 0;
- }
-
- Bundle ensureUserRestrictions() {
- if (userRestrictions == null) {
- userRestrictions = new Bundle();
- }
- return userRestrictions;
- }
-
- public void transfer(DeviceAdminInfo deviceAdminInfo) {
- if (hasParentActiveAdmin()) {
- parentAdmin.info = deviceAdminInfo;
- }
- info = deviceAdminInfo;
- }
-
- Bundle addSyntheticRestrictions(Bundle restrictions) {
- if (disableCamera) {
- restrictions.putBoolean(UserManager.DISALLOW_CAMERA, true);
- }
- if (requireAutoTime) {
- restrictions.putBoolean(UserManager.DISALLOW_CONFIG_DATE_TIME, true);
- }
- return restrictions;
- }
-
- static Bundle removeDeprecatedRestrictions(Bundle restrictions) {
- for (String deprecatedRestriction: DEPRECATED_USER_RESTRICTIONS) {
- restrictions.remove(deprecatedRestriction);
- }
- return restrictions;
- }
-
- static Bundle filterRestrictions(Bundle restrictions, Predicate<String> filter) {
- Bundle result = new Bundle();
- for (String key : restrictions.keySet()) {
- if (!restrictions.getBoolean(key)) {
- continue;
- }
- if (filter.test(key)) {
- result.putBoolean(key, true);
- }
- }
- return result;
- }
-
- Bundle getEffectiveRestrictions() {
- return addSyntheticRestrictions(
- removeDeprecatedRestrictions(new Bundle(ensureUserRestrictions())));
- }
-
- Bundle getLocalUserRestrictions(int adminType) {
- return filterRestrictions(getEffectiveRestrictions(),
- key -> UserRestrictionsUtils.isLocal(adminType, key));
- }
-
- Bundle getGlobalUserRestrictions(int adminType) {
- return filterRestrictions(getEffectiveRestrictions(),
- key -> UserRestrictionsUtils.isGlobal(adminType, key));
- }
-
- void dump(IndentingPrintWriter pw) {
- pw.print("uid="); pw.println(getUid());
- pw.print("testOnlyAdmin=");
- pw.println(testOnlyAdmin);
- pw.println("policies:");
- ArrayList<DeviceAdminInfo.PolicyInfo> pols = info.getUsedPolicies();
- if (pols != null) {
- pw.increaseIndent();
- for (int i=0; i<pols.size(); i++) {
- pw.println(pols.get(i).tag);
- }
- pw.decreaseIndent();
- }
- pw.print("passwordQuality=0x");
- pw.println(Integer.toHexString(mPasswordPolicy.quality));
- pw.print("minimumPasswordLength=");
- pw.println(mPasswordPolicy.length);
- pw.print("passwordHistoryLength=");
- pw.println(passwordHistoryLength);
- pw.print("minimumPasswordUpperCase=");
- pw.println(mPasswordPolicy.upperCase);
- pw.print("minimumPasswordLowerCase=");
- pw.println(mPasswordPolicy.lowerCase);
- pw.print("minimumPasswordLetters=");
- pw.println(mPasswordPolicy.letters);
- pw.print("minimumPasswordNumeric=");
- pw.println(mPasswordPolicy.numeric);
- pw.print("minimumPasswordSymbols=");
- pw.println(mPasswordPolicy.symbols);
- pw.print("minimumPasswordNonLetter=");
- pw.println(mPasswordPolicy.nonLetter);
- pw.print("maximumTimeToUnlock=");
- pw.println(maximumTimeToUnlock);
- pw.print("strongAuthUnlockTimeout=");
- pw.println(strongAuthUnlockTimeout);
- pw.print("maximumFailedPasswordsForWipe=");
- pw.println(maximumFailedPasswordsForWipe);
- pw.print("specifiesGlobalProxy=");
- pw.println(specifiesGlobalProxy);
- pw.print("passwordExpirationTimeout=");
- pw.println(passwordExpirationTimeout);
- pw.print("passwordExpirationDate=");
- pw.println(passwordExpirationDate);
- if (globalProxySpec != null) {
- pw.print("globalProxySpec=");
- pw.println(globalProxySpec);
- }
- if (globalProxyExclusionList != null) {
- pw.print("globalProxyEclusionList=");
- pw.println(globalProxyExclusionList);
- }
- pw.print("encryptionRequested=");
- pw.println(encryptionRequested);
- pw.print("disableCamera=");
- pw.println(disableCamera);
- pw.print("disableCallerId=");
- pw.println(disableCallerId);
- pw.print("disableContactsSearch=");
- pw.println(disableContactsSearch);
- pw.print("disableBluetoothContactSharing=");
- pw.println(disableBluetoothContactSharing);
- pw.print("disableScreenCapture=");
- pw.println(disableScreenCapture);
- pw.print("requireAutoTime=");
- pw.println(requireAutoTime);
- pw.print("forceEphemeralUsers=");
- pw.println(forceEphemeralUsers);
- pw.print("isNetworkLoggingEnabled=");
- pw.println(isNetworkLoggingEnabled);
- pw.print("disabledKeyguardFeatures=");
- pw.println(disabledKeyguardFeatures);
- pw.print("crossProfileWidgetProviders=");
- pw.println(crossProfileWidgetProviders);
- if (permittedAccessiblityServices != null) {
- pw.print("permittedAccessibilityServices=");
- pw.println(permittedAccessiblityServices);
- }
- if (permittedInputMethods != null) {
- pw.print("permittedInputMethods=");
- pw.println(permittedInputMethods);
- }
- if (permittedNotificationListeners != null) {
- pw.print("permittedNotificationListeners=");
- pw.println(permittedNotificationListeners);
- }
- if (keepUninstalledPackages != null) {
- pw.print("keepUninstalledPackages=");
- pw.println(keepUninstalledPackages);
- }
- pw.print("organizationColor=");
- pw.println(organizationColor);
- if (organizationName != null) {
- pw.print("organizationName=");
- pw.println(organizationName);
- }
- pw.println("userRestrictions:");
- UserRestrictionsUtils.dumpRestrictions(pw, " ", userRestrictions);
- pw.print("defaultEnabledRestrictionsAlreadySet=");
- pw.println(defaultEnabledRestrictionsAlreadySet);
- pw.print("isParent=");
- pw.println(isParent);
- if (parentAdmin != null) {
- pw.println("parentAdmin:");
- pw.increaseIndent();
- parentAdmin.dump(pw);
- pw.decreaseIndent();
- }
- if (mCrossProfileCalendarPackages != null) {
- pw.print("mCrossProfileCalendarPackages=");
- pw.println(mCrossProfileCalendarPackages);
- }
- pw.print("mCrossProfilePackages=");
- pw.println(mCrossProfilePackages);
- pw.print("mSuspendPersonalApps=");
- pw.println(mSuspendPersonalApps);
- pw.print("mProfileMaximumTimeOffMillis=");
- pw.println(mProfileMaximumTimeOffMillis);
- pw.print("mProfileOffDeadline=");
- pw.println(mProfileOffDeadline);
- pw.print("mAlwaysOnVpnPackage=");
- pw.println(mAlwaysOnVpnPackage);
- pw.print("mAlwaysOnVpnLockdown=");
- pw.println(mAlwaysOnVpnLockdown);
- pw.print("mCommonCriteriaMode=");
- pw.println(mCommonCriteriaMode);
- }
- }
-
private void handlePackagesChanged(@Nullable String packageName, int userHandle) {
boolean removedAdmin = false;
if (VERBOSE_LOG) {
@@ -2073,7 +934,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
if (removedAdmin) {
- validatePasswordOwnerLocked(policy);
+ policy.validatePasswordOwner();
}
boolean removedDelegate = false;
@@ -3514,13 +2375,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
-
- public DeviceAdminInfo findAdmin(final ComponentName adminName, final int userHandle,
+ private DeviceAdminInfo findAdmin(final ComponentName adminName, final int userHandle,
boolean throwForMissingPermission) {
- if (!mHasFeature) {
- return null;
- }
- enforceFullCrossUsersPermission(userHandle);
final ActivityInfo ai = mInjector.binderWithCleanCallingIdentity(() -> {
try {
return mIPackageManager.getReceiverInfo(adminName,
@@ -3583,213 +2439,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private void saveSettingsLocked(int userHandle) {
- DevicePolicyData policy = getUserData(userHandle);
- JournaledFile journal = makeJournaledFile(userHandle);
- FileOutputStream stream = null;
- try {
- stream = new FileOutputStream(journal.chooseForWrite(), false);
- XmlSerializer out = new FastXmlSerializer();
- out.setOutput(stream, StandardCharsets.UTF_8.name());
- out.startDocument(null, true);
-
- out.startTag(null, "policies");
- if (policy.mRestrictionsProvider != null) {
- out.attribute(null, ATTR_PERMISSION_PROVIDER,
- policy.mRestrictionsProvider.flattenToString());
- }
- if (policy.mUserSetupComplete) {
- out.attribute(null, ATTR_SETUP_COMPLETE,
- Boolean.toString(true));
- }
- if (policy.mPaired) {
- out.attribute(null, ATTR_DEVICE_PAIRED,
- Boolean.toString(true));
- }
- if (policy.mDeviceProvisioningConfigApplied) {
- out.attribute(null, ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED,
- Boolean.toString(true));
- }
- if (policy.mUserProvisioningState != DevicePolicyManager.STATE_USER_UNMANAGED) {
- out.attribute(null, ATTR_PROVISIONING_STATE,
- Integer.toString(policy.mUserProvisioningState));
- }
- if (policy.mPermissionPolicy != DevicePolicyManager.PERMISSION_POLICY_PROMPT) {
- out.attribute(null, ATTR_PERMISSION_POLICY,
- Integer.toString(policy.mPermissionPolicy));
- }
-
- // Serialize delegations.
- for (int i = 0; i < policy.mDelegationMap.size(); ++i) {
- final String delegatePackage = policy.mDelegationMap.keyAt(i);
- final List<String> scopes = policy.mDelegationMap.valueAt(i);
-
- // Every "delegation" tag serializes the information of one delegate-scope pair.
- for (String scope : scopes) {
- out.startTag(null, "delegation");
- out.attribute(null, "delegatePackage", delegatePackage);
- out.attribute(null, "scope", scope);
- out.endTag(null, "delegation");
- }
- }
-
- final int N = policy.mAdminList.size();
- for (int i=0; i<N; i++) {
- ActiveAdmin ap = policy.mAdminList.get(i);
- if (ap != null) {
- out.startTag(null, "admin");
- out.attribute(null, "name", ap.info.getComponent().flattenToString());
- ap.writeToXml(out);
- out.endTag(null, "admin");
- }
- }
-
- if (policy.mPasswordOwner >= 0) {
- out.startTag(null, "password-owner");
- out.attribute(null, "value", Integer.toString(policy.mPasswordOwner));
- out.endTag(null, "password-owner");
- }
-
- if (policy.mFailedPasswordAttempts != 0) {
- out.startTag(null, "failed-password-attempts");
- out.attribute(null, "value", Integer.toString(policy.mFailedPasswordAttempts));
- out.endTag(null, "failed-password-attempts");
- }
-
- // For FDE devices only, we save this flag so we can report on password sufficiency
- // before the user enters their password for the first time after a reboot. For
- // security reasons, we don't want to store the full set of active password metrics.
- if (!mInjector.storageManagerIsFileBasedEncryptionEnabled()) {
- out.startTag(null, TAG_PASSWORD_VALIDITY);
- out.attribute(null, ATTR_VALUE,
- Boolean.toString(policy.mPasswordValidAtLastCheckpoint));
- out.endTag(null, TAG_PASSWORD_VALIDITY);
- }
-
- for (int i = 0; i < policy.mAcceptedCaCertificates.size(); i++) {
- out.startTag(null, TAG_ACCEPTED_CA_CERTIFICATES);
- out.attribute(null, ATTR_NAME, policy.mAcceptedCaCertificates.valueAt(i));
- out.endTag(null, TAG_ACCEPTED_CA_CERTIFICATES);
- }
-
- for (int i=0; i<policy.mLockTaskPackages.size(); i++) {
- String component = policy.mLockTaskPackages.get(i);
- out.startTag(null, TAG_LOCK_TASK_COMPONENTS);
- out.attribute(null, "name", component);
- out.endTag(null, TAG_LOCK_TASK_COMPONENTS);
- }
-
- if (policy.mLockTaskFeatures != DevicePolicyManager.LOCK_TASK_FEATURE_NONE) {
- out.startTag(null, TAG_LOCK_TASK_FEATURES);
- out.attribute(null, ATTR_VALUE, Integer.toString(policy.mLockTaskFeatures));
- out.endTag(null, TAG_LOCK_TASK_FEATURES);
- }
-
- if (policy.mSecondaryLockscreenEnabled) {
- out.startTag(null, TAG_SECONDARY_LOCK_SCREEN);
- out.attribute(null, ATTR_VALUE, Boolean.toString(true));
- out.endTag(null, TAG_SECONDARY_LOCK_SCREEN);
- }
-
- if (policy.mStatusBarDisabled) {
- out.startTag(null, TAG_STATUS_BAR);
- out.attribute(null, ATTR_DISABLED, Boolean.toString(policy.mStatusBarDisabled));
- out.endTag(null, TAG_STATUS_BAR);
- }
-
- if (policy.doNotAskCredentialsOnBoot) {
- out.startTag(null, DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML);
- out.endTag(null, DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML);
- }
-
- for (String id : policy.mAffiliationIds) {
- out.startTag(null, TAG_AFFILIATION_ID);
- out.attribute(null, ATTR_ID, id);
- out.endTag(null, TAG_AFFILIATION_ID);
- }
-
- if (policy.mLastSecurityLogRetrievalTime >= 0) {
- out.startTag(null, TAG_LAST_SECURITY_LOG_RETRIEVAL);
- out.attribute(null, ATTR_VALUE,
- Long.toString(policy.mLastSecurityLogRetrievalTime));
- out.endTag(null, TAG_LAST_SECURITY_LOG_RETRIEVAL);
- }
-
- if (policy.mLastBugReportRequestTime >= 0) {
- out.startTag(null, TAG_LAST_BUG_REPORT_REQUEST);
- out.attribute(null, ATTR_VALUE,
- Long.toString(policy.mLastBugReportRequestTime));
- out.endTag(null, TAG_LAST_BUG_REPORT_REQUEST);
- }
-
- if (policy.mLastNetworkLogsRetrievalTime >= 0) {
- out.startTag(null, TAG_LAST_NETWORK_LOG_RETRIEVAL);
- out.attribute(null, ATTR_VALUE,
- Long.toString(policy.mLastNetworkLogsRetrievalTime));
- out.endTag(null, TAG_LAST_NETWORK_LOG_RETRIEVAL);
- }
-
- if (policy.mAdminBroadcastPending) {
- out.startTag(null, TAG_ADMIN_BROADCAST_PENDING);
- out.attribute(null, ATTR_VALUE,
- Boolean.toString(policy.mAdminBroadcastPending));
- out.endTag(null, TAG_ADMIN_BROADCAST_PENDING);
- }
-
- if (policy.mInitBundle != null) {
- out.startTag(null, TAG_INITIALIZATION_BUNDLE);
- policy.mInitBundle.saveToXml(out);
- out.endTag(null, TAG_INITIALIZATION_BUNDLE);
- }
-
- if (policy.mPasswordTokenHandle != 0) {
- out.startTag(null, TAG_PASSWORD_TOKEN_HANDLE);
- out.attribute(null, ATTR_VALUE,
- Long.toString(policy.mPasswordTokenHandle));
- out.endTag(null, TAG_PASSWORD_TOKEN_HANDLE);
- }
-
- if (policy.mCurrentInputMethodSet) {
- out.startTag(null, TAG_CURRENT_INPUT_METHOD_SET);
- out.endTag(null, TAG_CURRENT_INPUT_METHOD_SET);
- }
-
- for (final String cert : policy.mOwnerInstalledCaCerts) {
- out.startTag(null, TAG_OWNER_INSTALLED_CA_CERT);
- out.attribute(null, ATTR_ALIAS, cert);
- out.endTag(null, TAG_OWNER_INSTALLED_CA_CERT);
- }
-
- for (int i = 0, size = policy.mUserControlDisabledPackages.size(); i < size; i++) {
- String packageName = policy.mUserControlDisabledPackages.get(i);
- out.startTag(null, TAG_PROTECTED_PACKAGES);
- out.attribute(null, ATTR_NAME, packageName);
- out.endTag(null, TAG_PROTECTED_PACKAGES);
- }
-
- if (policy.mAppsSuspended) {
- out.startTag(null, TAG_APPS_SUSPENDED);
- out.attribute(null, ATTR_VALUE, Boolean.toString(policy.mAppsSuspended));
- out.endTag(null, TAG_APPS_SUSPENDED);
- }
-
- out.endTag(null, "policies");
-
- out.endDocument();
- stream.flush();
- FileUtils.sync(stream);
- stream.close();
- journal.commit();
+ if (DevicePolicyData.store(
+ getUserData(userHandle),
+ makeJournaledFile(userHandle),
+ !mInjector.storageManagerIsFileBasedEncryptionEnabled())) {
sendChangedNotification(userHandle);
- } catch (XmlPullParserException | IOException e) {
- Slog.w(LOG_TAG, "failed writing file", e);
- try {
- if (stream != null) {
- stream.close();
- }
- } catch (IOException ex) {
- // Ignore
- }
- journal.rollback();
}
}
@@ -3801,225 +2455,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private void loadSettingsLocked(DevicePolicyData policy, int userHandle) {
- JournaledFile journal = makeJournaledFile(userHandle);
- FileInputStream stream = null;
- File file = journal.chooseForRead();
- boolean needsRewrite = false;
- try {
- stream = new FileInputStream(file);
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(stream, StandardCharsets.UTF_8.name());
-
- int type;
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && type != XmlPullParser.START_TAG) {
- }
- String tag = parser.getName();
- if (!"policies".equals(tag)) {
- throw new XmlPullParserException(
- "Settings do not start with policies tag: found " + tag);
- }
-
- // Extract the permission provider component name if available
- String permissionProvider = parser.getAttributeValue(null, ATTR_PERMISSION_PROVIDER);
- if (permissionProvider != null) {
- policy.mRestrictionsProvider = ComponentName.unflattenFromString(permissionProvider);
- }
- String userSetupComplete = parser.getAttributeValue(null, ATTR_SETUP_COMPLETE);
- if (userSetupComplete != null && Boolean.toString(true).equals(userSetupComplete)) {
- policy.mUserSetupComplete = true;
- }
- String paired = parser.getAttributeValue(null, ATTR_DEVICE_PAIRED);
- if (paired != null && Boolean.toString(true).equals(paired)) {
- policy.mPaired = true;
- }
- String deviceProvisioningConfigApplied = parser.getAttributeValue(null,
- ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED);
- if (deviceProvisioningConfigApplied != null
- && Boolean.toString(true).equals(deviceProvisioningConfigApplied)) {
- policy.mDeviceProvisioningConfigApplied = true;
- }
- String provisioningState = parser.getAttributeValue(null, ATTR_PROVISIONING_STATE);
- if (!TextUtils.isEmpty(provisioningState)) {
- policy.mUserProvisioningState = Integer.parseInt(provisioningState);
- }
- String permissionPolicy = parser.getAttributeValue(null, ATTR_PERMISSION_POLICY);
- if (!TextUtils.isEmpty(permissionPolicy)) {
- policy.mPermissionPolicy = Integer.parseInt(permissionPolicy);
- }
- // Check for delegation compatibility with pre-O.
- // TODO(edmanp) remove in P.
- {
- final String certDelegate = parser.getAttributeValue(null,
- ATTR_DELEGATED_CERT_INSTALLER);
- if (certDelegate != null) {
- List<String> scopes = policy.mDelegationMap.get(certDelegate);
- if (scopes == null) {
- scopes = new ArrayList<>();
- policy.mDelegationMap.put(certDelegate, scopes);
- }
- if (!scopes.contains(DELEGATION_CERT_INSTALL)) {
- scopes.add(DELEGATION_CERT_INSTALL);
- needsRewrite = true;
- }
- }
- final String appRestrictionsDelegate = parser.getAttributeValue(null,
- ATTR_APPLICATION_RESTRICTIONS_MANAGER);
- if (appRestrictionsDelegate != null) {
- List<String> scopes = policy.mDelegationMap.get(appRestrictionsDelegate);
- if (scopes == null) {
- scopes = new ArrayList<>();
- policy.mDelegationMap.put(appRestrictionsDelegate, scopes);
- }
- if (!scopes.contains(DELEGATION_APP_RESTRICTIONS)) {
- scopes.add(DELEGATION_APP_RESTRICTIONS);
- needsRewrite = true;
- }
- }
- }
-
- type = parser.next();
- int outerDepth = parser.getDepth();
- policy.mLockTaskPackages.clear();
- policy.mAdminList.clear();
- policy.mAdminMap.clear();
- policy.mAffiliationIds.clear();
- policy.mOwnerInstalledCaCerts.clear();
- policy.mUserControlDisabledPackages.clear();
- while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
- tag = parser.getName();
- if ("admin".equals(tag)) {
- String name = parser.getAttributeValue(null, "name");
- try {
- DeviceAdminInfo dai = findAdmin(
- ComponentName.unflattenFromString(name), userHandle,
- /* throwForMissingPermission= */ false);
- if (VERBOSE_LOG
- && (UserHandle.getUserId(dai.getActivityInfo().applicationInfo.uid)
- != userHandle)) {
- Slog.w(LOG_TAG, "findAdmin returned an incorrect uid "
- + dai.getActivityInfo().applicationInfo.uid + " for user "
- + userHandle);
- }
- if (dai != null) {
- boolean shouldOverwritePolicies =
- shouldOverwritePoliciesFromXml(dai.getComponent(), userHandle);
- ActiveAdmin ap = new ActiveAdmin(dai, /* parent */ false);
- ap.readFromXml(parser, shouldOverwritePolicies);
- policy.mAdminMap.put(ap.info.getComponent(), ap);
- }
- } catch (RuntimeException e) {
- Slog.w(LOG_TAG, "Failed loading admin " + name, e);
- }
- } else if ("delegation".equals(tag)) {
- // Parse delegation info.
- final String delegatePackage = parser.getAttributeValue(null,
- "delegatePackage");
- final String scope = parser.getAttributeValue(null, "scope");
-
- // Get a reference to the scopes list for the delegatePackage.
- List<String> scopes = policy.mDelegationMap.get(delegatePackage);
- // Or make a new list if none was found.
- if (scopes == null) {
- scopes = new ArrayList<>();
- policy.mDelegationMap.put(delegatePackage, scopes);
- }
- // Add the new scope to the list of delegatePackage if it's not already there.
- if (!scopes.contains(scope)) {
- scopes.add(scope);
- }
- } else if ("failed-password-attempts".equals(tag)) {
- policy.mFailedPasswordAttempts = Integer.parseInt(
- parser.getAttributeValue(null, "value"));
- } else if ("password-owner".equals(tag)) {
- policy.mPasswordOwner = Integer.parseInt(
- parser.getAttributeValue(null, "value"));
- } else if (TAG_ACCEPTED_CA_CERTIFICATES.equals(tag)) {
- policy.mAcceptedCaCertificates.add(parser.getAttributeValue(null, ATTR_NAME));
- } else if (TAG_LOCK_TASK_COMPONENTS.equals(tag)) {
- policy.mLockTaskPackages.add(parser.getAttributeValue(null, "name"));
- } else if (TAG_LOCK_TASK_FEATURES.equals(tag)) {
- policy.mLockTaskFeatures = Integer.parseInt(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_SECONDARY_LOCK_SCREEN.equals(tag)) {
- policy.mSecondaryLockscreenEnabled = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_STATUS_BAR.equals(tag)) {
- policy.mStatusBarDisabled = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_DISABLED));
- } else if (DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML.equals(tag)) {
- policy.doNotAskCredentialsOnBoot = true;
- } else if (TAG_AFFILIATION_ID.equals(tag)) {
- policy.mAffiliationIds.add(parser.getAttributeValue(null, ATTR_ID));
- } else if (TAG_LAST_SECURITY_LOG_RETRIEVAL.equals(tag)) {
- policy.mLastSecurityLogRetrievalTime = Long.parseLong(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_LAST_BUG_REPORT_REQUEST.equals(tag)) {
- policy.mLastBugReportRequestTime = Long.parseLong(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_LAST_NETWORK_LOG_RETRIEVAL.equals(tag)) {
- policy.mLastNetworkLogsRetrievalTime = Long.parseLong(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_ADMIN_BROADCAST_PENDING.equals(tag)) {
- String pending = parser.getAttributeValue(null, ATTR_VALUE);
- policy.mAdminBroadcastPending = Boolean.toString(true).equals(pending);
- } else if (TAG_INITIALIZATION_BUNDLE.equals(tag)) {
- policy.mInitBundle = PersistableBundle.restoreFromXml(parser);
- } else if ("active-password".equals(tag)) {
- // Remove password metrics from saved settings, as we no longer wish to store
- // these on disk
- needsRewrite = true;
- } else if (TAG_PASSWORD_VALIDITY.equals(tag)) {
- if (!mInjector.storageManagerIsFileBasedEncryptionEnabled()) {
- // This flag is only used for FDE devices
- policy.mPasswordValidAtLastCheckpoint = Boolean.parseBoolean(
- parser.getAttributeValue(null, ATTR_VALUE));
- }
- } else if (TAG_PASSWORD_TOKEN_HANDLE.equals(tag)) {
- policy.mPasswordTokenHandle = Long.parseLong(
- parser.getAttributeValue(null, ATTR_VALUE));
- } else if (TAG_CURRENT_INPUT_METHOD_SET.equals(tag)) {
- policy.mCurrentInputMethodSet = true;
- } else if (TAG_OWNER_INSTALLED_CA_CERT.equals(tag)) {
- policy.mOwnerInstalledCaCerts.add(parser.getAttributeValue(null, ATTR_ALIAS));
- } else if (TAG_PROTECTED_PACKAGES.equals(tag)) {
- policy.mUserControlDisabledPackages.add(
- parser.getAttributeValue(null, ATTR_NAME));
- } else if (TAG_APPS_SUSPENDED.equals(tag)) {
- policy.mAppsSuspended =
- Boolean.parseBoolean(parser.getAttributeValue(null, ATTR_VALUE));
- } else {
- Slog.w(LOG_TAG, "Unknown tag: " + tag);
- XmlUtils.skipCurrentTag(parser);
- }
- }
- } catch (FileNotFoundException e) {
- // Don't be noisy, this is normal if we haven't defined any policies.
- } catch (NullPointerException | NumberFormatException | XmlPullParserException | IOException
- | IndexOutOfBoundsException e) {
- Slog.w(LOG_TAG, "failed parsing " + file, e);
- }
- try {
- if (stream != null) {
- stream.close();
- }
- } catch (IOException e) {
- // Ignore
- }
-
- // Generate a list of admins from the admin map
- policy.mAdminList.addAll(policy.mAdminMap.values());
+ boolean needsRewrite = DevicePolicyData.load(policy,
+ !mInjector.storageManagerIsFileBasedEncryptionEnabled(),
+ makeJournaledFile(userHandle),
+ component -> findAdmin(
+ component, userHandle, /* throwForMissingPermission= */ false),
+ getOwnerComponent(userHandle));
// Might need to upgrade the file by rewriting it
if (needsRewrite) {
saveSettingsLocked(userHandle);
}
- validatePasswordOwnerLocked(policy);
+ policy.validatePasswordOwner();
updateMaximumTimeToLockLocked(userHandle);
updateLockTaskPackagesLocked(policy.mLockTaskPackages, userHandle);
updateLockTaskFeaturesLocked(policy.mLockTaskFeatures, userHandle);
@@ -4029,14 +2477,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
- private boolean shouldOverwritePoliciesFromXml(
- ComponentName deviceAdminComponent, int userHandle) {
- // http://b/123415062: If DA, overwrite with the stored policies that were agreed by the
- // user to prevent apps from sneaking additional policies into updates.
- return !isProfileOwner(deviceAdminComponent, userHandle)
- && !isDeviceOwner(deviceAdminComponent, userHandle);
- }
-
private void updateLockTaskPackagesLocked(List<String> packages, int userId) {
long ident = mInjector.binderClearCallingIdentity();
try {
@@ -4098,23 +2538,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
+ Integer.toHexString(quality));
}
- void validatePasswordOwnerLocked(DevicePolicyData policy) {
- if (policy.mPasswordOwner >= 0) {
- boolean haveOwner = false;
- for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
- if (policy.mAdminList.get(i).getUid() == policy.mPasswordOwner) {
- haveOwner = true;
- break;
- }
- }
- if (!haveOwner) {
- Slog.w(LOG_TAG, "Previous password owner " + policy.mPasswordOwner
- + " no longer active; disabling");
- policy.mPasswordOwner = -1;
- }
- }
- }
-
@VisibleForTesting
@Override
void systemReady(int phase) {
@@ -5842,8 +4265,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private void setDoNotAskCredentialsOnBoot() {
synchronized (getLockObject()) {
DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM);
- if (!policyData.doNotAskCredentialsOnBoot) {
- policyData.doNotAskCredentialsOnBoot = true;
+ if (!policyData.mDoNotAskCredentialsOnBoot) {
+ policyData.mDoNotAskCredentialsOnBoot = true;
saveSettingsLocked(UserHandle.USER_SYSTEM);
}
}
@@ -5855,7 +4278,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
android.Manifest.permission.QUERY_DO_NOT_ASK_CREDENTIALS_ON_BOOT, null);
synchronized (getLockObject()) {
DevicePolicyData policyData = getUserData(UserHandle.USER_SYSTEM);
- return policyData.doNotAskCredentialsOnBoot;
+ return policyData.mDoNotAskCredentialsOnBoot;
}
}
@@ -14363,7 +12786,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
policy.mAdminList.remove(admin);
policy.mAdminMap.remove(adminReceiver);
- validatePasswordOwnerLocked(policy);
+ policy.validatePasswordOwner();
if (doProxyCleanup) {
resetGlobalProxyLocked(policy);
}
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index a5f0d045948c..f7082a9a1a0c 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -23,7 +23,6 @@
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <binder/AppOpsManager.h>
-#include <binder/Nullable.h>
#include <binder/Status.h>
#include <sys/stat.h>
#include <uuid/uuid.h>
@@ -1404,7 +1403,7 @@ void IncrementalService::prepareDataLoaderLocked(IncFsMount& ifs, DataLoaderPara
}
FileSystemControlParcel fsControlParcel;
- fsControlParcel.incremental = aidl::make_nullable<IncrementalFileSystemControlParcel>();
+ fsControlParcel.incremental = std::make_optional<IncrementalFileSystemControlParcel>();
fsControlParcel.incremental->cmd.reset(dup(ifs.control.cmd()));
fsControlParcel.incremental->pendingReads.reset(dup(ifs.control.pendingReads()));
fsControlParcel.incremental->log.reset(dup(ifs.control.logs()));
diff --git a/services/systemcaptions/java/com/android/server/systemcaptions/SystemCaptionsManagerService.java b/services/systemcaptions/java/com/android/server/systemcaptions/SystemCaptionsManagerService.java
index 27a116c8043e..1586a33ba0e9 100644
--- a/services/systemcaptions/java/com/android/server/systemcaptions/SystemCaptionsManagerService.java
+++ b/services/systemcaptions/java/com/android/server/systemcaptions/SystemCaptionsManagerService.java
@@ -34,7 +34,8 @@ public final class SystemCaptionsManagerService extends
context,
com.android.internal.R.string.config_defaultSystemCaptionsManagerService),
/*disallowProperty=*/ null,
- /*packageUpdatePolicy=*/ PACKAGE_UPDATE_POLICY_REFRESH_EAGER);
+ /*packageUpdatePolicy=*/ PACKAGE_UPDATE_POLICY_REFRESH_EAGER
+ | PACKAGE_RESTART_POLICY_REFRESH_EAGER);
}
@Override
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
index 1cb004a6dc1e..fdcadf3e3088 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
@@ -25,6 +25,7 @@ import static android.location.Criteria.ACCURACY_COARSE;
import static android.location.Criteria.ACCURACY_FINE;
import static android.location.Criteria.POWER_HIGH;
import static android.location.LocationManager.PASSIVE_PROVIDER;
+import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF;
import static androidx.test.ext.truth.location.LocationSubject.assertThat;
@@ -907,6 +908,21 @@ public class LocationProviderManagerTest {
assertThat(mProvider.getRequest().interval).isEqualTo(5);
}
+ @Test
+ public void testProviderRequest_BatterySaver_ScreenOnOff() {
+ mInjector.getLocationPowerSaveModeHelper().setLocationPowerSaveMode(
+ LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF);
+
+ ILocationListener listener = createMockLocationListener();
+ LocationRequest request = LocationRequest.createFromDeprecatedProvider(NAME, 5, 0, false);
+ mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
+
+ assertThat(mProvider.getRequest().reportLocation).isTrue();
+
+ mInjector.getScreenInteractiveHelper().setScreenInteractive(false);
+ assertThat(mProvider.getRequest().reportLocation).isFalse();
+ }
+
private ILocationListener createMockLocationListener() {
return spy(new ILocationListener.Stub() {
@Override
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-lists-whitelist-format.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-lists-allowlist-format.xml
index 597600303acb..597600303acb 100644
--- a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-lists-whitelist-format.xml
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/restrict-background-lists-allowlist-format.xml
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-off.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-allowlisted-restrict-background-off.xml
index 196ca28192e4..196ca28192e4 100644
--- a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-off.xml
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-allowlisted-restrict-background-off.xml
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-on.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-allowlisted-restrict-background-on.xml
index 4b7724c05d8d..4b7724c05d8d 100644
--- a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-whitelisted-restrict-background-on.xml
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-allowlisted-restrict-background-on.xml
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-off.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-denylisted-restrict-background-off.xml
index 5b1c03ce170e..5b1c03ce170e 100644
--- a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-off.xml
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-denylisted-restrict-background-off.xml
diff --git a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-on.xml b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-denylisted-restrict-background-on.xml
index bec2371cff6f..bec2371cff6f 100644
--- a/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-blacklisted-restrict-background-on.xml
+++ b/services/tests/servicestests/assets/NetworkPolicyManagerServiceTest/netpolicy/uidA-denylisted-restrict-background-on.xml
diff --git a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
index 7d6d90c4578c..02d10e3b6ce1 100644
--- a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
@@ -21,7 +21,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
@@ -310,7 +309,7 @@ public class VibratorServiceTest {
verify(mNativeWrapperMock).vibratorPerformEffect(
eq((long) VibrationEffect.EFFECT_CLICK),
eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG),
- any(VibratorService.Vibration.class), eq(false));
+ any(VibratorService.Vibration.class));
}
@Test
@@ -387,21 +386,26 @@ public class VibratorServiceTest {
}
@Test
- public void vibrate_withOneShotAndNativeCallbackNotTriggered_finishesVibrationViaFallback() {
+ public void vibrate_withPrebakedAndNativeCallbackTriggered_finishesVibration() {
+ when(mNativeWrapperMock.vibratorGetSupportedEffects())
+ .thenReturn(new int[]{VibrationEffect.EFFECT_CLICK});
+ doAnswer(invocation -> {
+ ((VibratorService.Vibration) invocation.getArgument(2)).onComplete();
+ return 10_000L; // 10s
+ }).when(mNativeWrapperMock).vibratorPerformEffect(
+ anyLong(), anyLong(), any(VibratorService.Vibration.class));
VibratorService service = createService();
Mockito.clearInvocations(mNativeWrapperMock);
- vibrate(service, VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE));
-
- verify(mNativeWrapperMock).vibratorOff();
- verify(mNativeWrapperMock).vibratorOn(eq(100L), any(VibratorService.Vibration.class));
- Mockito.clearInvocations(mNativeWrapperMock);
-
- // Run the scheduled callback to finish one-shot vibration.
- mTestLooper.moveTimeForward(200);
- mTestLooper.dispatchAll();
+ vibrate(service, VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK));
- verify(mNativeWrapperMock).vibratorOff();
+ InOrder inOrderVerifier = inOrder(mNativeWrapperMock);
+ inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
+ inOrderVerifier.verify(mNativeWrapperMock).vibratorPerformEffect(
+ eq((long) VibrationEffect.EFFECT_CLICK),
+ eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG),
+ any(VibratorService.Vibration.class));
+ inOrderVerifier.verify(mNativeWrapperMock).vibratorOff();
}
@Test
@@ -447,30 +451,6 @@ public class VibratorServiceTest {
}
@Test
- public void vibrate_withComposedAndNativeCallbackNotTriggered_finishesVibrationViaFallback() {
- mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
- VibratorService service = createService();
- Mockito.clearInvocations(mNativeWrapperMock);
-
- VibrationEffect effect = VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, 10)
- .compose();
- vibrate(service, effect);
-
- verify(mNativeWrapperMock).vibratorOff();
- verify(mNativeWrapperMock).vibratorPerformComposedEffect(
- any(VibrationEffect.Composition.PrimitiveEffect[].class),
- any(VibratorService.Vibration.class));
- Mockito.clearInvocations(mNativeWrapperMock);
-
- // Run the scheduled callback to finish one-shot vibration.
- mTestLooper.moveTimeForward(10000); // 10s
- mTestLooper.dispatchAll();
-
- verify(mNativeWrapperMock).vibratorOff();
- }
-
- @Test
public void vibrate_whenBinderDies_cancelsVibration() {
mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS);
doAnswer(invocation -> {
@@ -574,15 +554,15 @@ public class VibratorServiceTest {
verify(mNativeWrapperMock).vibratorPerformEffect(
eq((long) VibrationEffect.EFFECT_CLICK),
- eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG), any(), anyBoolean());
+ eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG), any());
verify(mNativeWrapperMock).vibratorPerformEffect(
eq((long) VibrationEffect.EFFECT_TICK),
- eq((long) VibrationEffect.EFFECT_STRENGTH_MEDIUM), any(), anyBoolean());
+ eq((long) VibrationEffect.EFFECT_STRENGTH_MEDIUM), any());
verify(mNativeWrapperMock).vibratorPerformEffect(
eq((long) VibrationEffect.EFFECT_DOUBLE_CLICK),
- eq((long) VibrationEffect.EFFECT_STRENGTH_LIGHT), any(), anyBoolean());
+ eq((long) VibrationEffect.EFFECT_STRENGTH_LIGHT), any());
verify(mNativeWrapperMock, never()).vibratorPerformEffect(
- eq((long) VibrationEffect.EFFECT_HEAVY_CLICK), anyLong(), any(), anyBoolean());
+ eq((long) VibrationEffect.EFFECT_HEAVY_CLICK), anyLong(), any());
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 9a465a91e84e..8fc228734f37 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -1604,7 +1604,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.setApplicationRestrictionsManagingPackage(admin1, RESTRICTIONS_DELEGATE);
// DPMS correctly stores and retrieves the delegates
- DevicePolicyManagerService.DevicePolicyData policy = dpms.mUserData.get(userHandle);
+ DevicePolicyData policy = dpms.mUserData.get(userHandle);
assertEquals(2, policy.mDelegationMap.size());
MoreAsserts.assertContentsInAnyOrder(policy.mDelegationMap.get(CERT_DELEGATE),
DELEGATION_CERT_INSTALL);
@@ -1846,11 +1846,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {
reset(getServices().userManagerInternal);
}
- private DevicePolicyManagerService.ActiveAdmin getDeviceOwner() {
+ private ActiveAdmin getDeviceOwner() {
ComponentName component = dpms.mOwners.getDeviceOwnerComponent();
- DevicePolicyManagerService.DevicePolicyData policy =
+ DevicePolicyData policy =
dpms.getUserData(dpms.mOwners.getDeviceOwnerUserId());
- for (DevicePolicyManagerService.ActiveAdmin admin : policy.mAdminList) {
+ for (ActiveAdmin admin : policy.mAdminList) {
if (component.equals(admin.info.getComponent())) {
return admin;
}
@@ -3745,8 +3745,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setUserSetupCompleteForUser(false, userId);
// GIVEN userComplete is true in DPM
- DevicePolicyManagerService.DevicePolicyData userData =
- new DevicePolicyManagerService.DevicePolicyData(userId);
+ DevicePolicyData userData = new DevicePolicyData(userId);
userData.mUserSetupComplete = true;
dpms.mUserData.put(UserHandle.USER_SYSTEM, userData);
@@ -3770,8 +3769,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setUserSetupCompleteForUser(false, userId);
// GIVEN userComplete is true in DPM
- DevicePolicyManagerService.DevicePolicyData userData =
- new DevicePolicyManagerService.DevicePolicyData(userId);
+ DevicePolicyData userData = new DevicePolicyData(userId);
userData.mUserSetupComplete = true;
dpms.mUserData.put(UserHandle.USER_SYSTEM, userData);
diff --git a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java
index e4c9cc3c05d9..1d914ec083fa 100644
--- a/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/inputmethod/InputMethodUtilsTest.java
@@ -88,36 +88,36 @@ public class InputMethodUtilsTest {
public void testVoiceImes() throws Exception {
// locale: en_US
assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_US,
- "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
+ "FakeDefaultEnKeyboardIme", "FakeDefaultAutoVoiceIme");
assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_US,
- "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0",
- "DummyNonDefaultAutoVoiceIme1");
+ "FakeDefaultEnKeyboardIme", "FakeNonDefaultAutoVoiceIme0",
+ "FakeNonDefaultAutoVoiceIme1");
assertDefaultEnabledMinimumImes(getImesWithDefaultVoiceIme(), LOCALE_EN_US,
- "DummyDefaultEnKeyboardIme");
+ "FakeDefaultEnKeyboardIme");
assertDefaultEnabledMinimumImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_US,
- "DummyDefaultEnKeyboardIme");
+ "FakeDefaultEnKeyboardIme");
// locale: en_GB
assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_EN_GB,
- "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
+ "FakeDefaultEnKeyboardIme", "FakeDefaultAutoVoiceIme");
assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_GB,
- "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0",
- "DummyNonDefaultAutoVoiceIme1");
+ "FakeDefaultEnKeyboardIme", "FakeNonDefaultAutoVoiceIme0",
+ "FakeNonDefaultAutoVoiceIme1");
assertDefaultEnabledMinimumImes(getImesWithDefaultVoiceIme(), LOCALE_EN_GB,
- "DummyDefaultEnKeyboardIme");
+ "FakeDefaultEnKeyboardIme");
assertDefaultEnabledMinimumImes(getImesWithoutDefaultVoiceIme(), LOCALE_EN_GB,
- "DummyDefaultEnKeyboardIme");
+ "FakeDefaultEnKeyboardIme");
// locale: ja_JP
assertDefaultEnabledImes(getImesWithDefaultVoiceIme(), LOCALE_JA_JP,
- "DummyDefaultEnKeyboardIme", "DummyDefaultAutoVoiceIme");
+ "FakeDefaultEnKeyboardIme", "FakeDefaultAutoVoiceIme");
assertDefaultEnabledImes(getImesWithoutDefaultVoiceIme(), LOCALE_JA_JP,
- "DummyDefaultEnKeyboardIme", "DummyNonDefaultAutoVoiceIme0",
- "DummyNonDefaultAutoVoiceIme1");
+ "FakeDefaultEnKeyboardIme", "FakeNonDefaultAutoVoiceIme0",
+ "FakeNonDefaultAutoVoiceIme1");
assertDefaultEnabledMinimumImes(getImesWithDefaultVoiceIme(), LOCALE_JA_JP,
- "DummyDefaultEnKeyboardIme");
+ "FakeDefaultEnKeyboardIme");
assertDefaultEnabledMinimumImes(getImesWithoutDefaultVoiceIme(), LOCALE_JA_JP,
- "DummyDefaultEnKeyboardIme");
+ "FakeDefaultEnKeyboardIme");
}
@Test
@@ -189,67 +189,67 @@ public class InputMethodUtilsTest {
@Test
public void testGetImplicitlyApplicableSubtypesLocked() throws Exception {
- final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US",
+ final InputMethodSubtype nonAutoEnUS = createFakeInputMethodSubtype("en_US",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB",
+ final InputMethodSubtype nonAutoEnGB = createFakeInputMethodSubtype("en_GB",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoEnIN = createDummyInputMethodSubtype("en_IN",
+ final InputMethodSubtype nonAutoEnIN = createFakeInputMethodSubtype("en_IN",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoFrCA = createDummyInputMethodSubtype("fr_CA",
+ final InputMethodSubtype nonAutoFrCA = createFakeInputMethodSubtype("fr_CA",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoFr = createDummyInputMethodSubtype("fr_CA",
+ final InputMethodSubtype nonAutoFr = createFakeInputMethodSubtype("fr_CA",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoFil = createDummyInputMethodSubtype("fil",
+ final InputMethodSubtype nonAutoFil = createFakeInputMethodSubtype("fil",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoIn = createDummyInputMethodSubtype("in",
+ final InputMethodSubtype nonAutoIn = createFakeInputMethodSubtype("in",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoId = createDummyInputMethodSubtype("id",
+ final InputMethodSubtype nonAutoId = createFakeInputMethodSubtype("id",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype autoSubtype = createDummyInputMethodSubtype("auto",
+ final InputMethodSubtype autoSubtype = createFakeInputMethodSubtype("auto",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoJa = createDummyInputMethodSubtype("ja",
+ final InputMethodSubtype nonAutoJa = createFakeInputMethodSubtype("ja",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
!IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoHi = createDummyInputMethodSubtype("hi",
+ final InputMethodSubtype nonAutoHi = createFakeInputMethodSubtype("hi",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
!IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoSrCyrl = createDummyInputMethodSubtype("sr",
+ final InputMethodSubtype nonAutoSrCyrl = createFakeInputMethodSubtype("sr",
"sr-Cyrl", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoSrLatn = createDummyInputMethodSubtype("sr_ZZ",
+ final InputMethodSubtype nonAutoSrLatn = createFakeInputMethodSubtype("sr_ZZ",
"sr-Latn", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoHandwritingEn = createDummyInputMethodSubtype("en",
+ final InputMethodSubtype nonAutoHandwritingEn = createFakeInputMethodSubtype("en",
SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
!IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoHandwritingFr = createDummyInputMethodSubtype("fr",
+ final InputMethodSubtype nonAutoHandwritingFr = createFakeInputMethodSubtype("fr",
SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
!IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoHandwritingSrCyrl = createDummyInputMethodSubtype("sr",
+ final InputMethodSubtype nonAutoHandwritingSrCyrl = createFakeInputMethodSubtype("sr",
"sr-Cyrl", SUBTYPE_MODE_HANDWRITING, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoHandwritingSrLatn = createDummyInputMethodSubtype("sr_ZZ",
+ final InputMethodSubtype nonAutoHandwritingSrLatn = createFakeInputMethodSubtype("sr_ZZ",
"sr-Latn", SUBTYPE_MODE_HANDWRITING, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype =
- createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ createFakeInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2 =
- createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ createFakeInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
@@ -266,9 +266,9 @@ public class InputMethodUtilsTest {
subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
subtypes.add(nonAutoHandwritingEn);
subtypes.add(nonAutoHandwritingFr);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -290,9 +290,9 @@ public class InputMethodUtilsTest {
subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
subtypes.add(nonAutoHandwritingEn);
subtypes.add(nonAutoHandwritingFr);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -314,9 +314,9 @@ public class InputMethodUtilsTest {
subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
subtypes.add(nonAutoHandwritingEn);
subtypes.add(nonAutoHandwritingFr);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -339,9 +339,9 @@ public class InputMethodUtilsTest {
subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
subtypes.add(nonAutoHandwritingEn);
subtypes.add(nonAutoHandwritingFr);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -360,9 +360,9 @@ public class InputMethodUtilsTest {
subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
subtypes.add(nonAutoHandwritingEn);
subtypes.add(nonAutoHandwritingFr);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -382,9 +382,9 @@ public class InputMethodUtilsTest {
subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
subtypes.add(nonAutoHandwritingEn);
subtypes.add(nonAutoHandwritingFr);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -404,9 +404,9 @@ public class InputMethodUtilsTest {
subtypes.add(nonAutoHandwritingEn);
subtypes.add(nonAutoHandwritingFr);
subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -421,9 +421,9 @@ public class InputMethodUtilsTest {
subtypes.add(nonAutoHandwritingEn);
subtypes.add(nonAutoHandwritingFr);
subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -438,9 +438,9 @@ public class InputMethodUtilsTest {
subtypes.add(nonAutoEnUS);
subtypes.add(nonAutoHi);
subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -460,9 +460,9 @@ public class InputMethodUtilsTest {
subtypes.add(nonAutoHandwritingFr);
subtypes.add(nonAutoHandwritingSrCyrl);
subtypes.add(nonAutoHandwritingSrLatn);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -480,9 +480,9 @@ public class InputMethodUtilsTest {
subtypes.add(nonAutoHandwritingFr);
subtypes.add(nonAutoHandwritingSrCyrl);
subtypes.add(nonAutoHandwritingSrLatn);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -506,9 +506,9 @@ public class InputMethodUtilsTest {
subtypes.add(nonAutoHandwritingFr);
subtypes.add(nonAutoHandwritingSrCyrl);
subtypes.add(nonAutoHandwritingSrLatn);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -533,9 +533,9 @@ public class InputMethodUtilsTest {
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
subtypes.add(nonAutoEnUS);
subtypes.add(nonAutoFil);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -551,9 +551,9 @@ public class InputMethodUtilsTest {
subtypes.add(nonAutoJa);
subtypes.add(nonAutoEnUS);
subtypes.add(nonAutoFil);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -567,9 +567,9 @@ public class InputMethodUtilsTest {
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
subtypes.add(nonAutoIn);
subtypes.add(nonAutoEnUS);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -581,9 +581,9 @@ public class InputMethodUtilsTest {
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
subtypes.add(nonAutoIn);
subtypes.add(nonAutoEnUS);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -595,9 +595,9 @@ public class InputMethodUtilsTest {
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
subtypes.add(nonAutoId);
subtypes.add(nonAutoEnUS);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -609,9 +609,9 @@ public class InputMethodUtilsTest {
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
subtypes.add(nonAutoId);
subtypes.add(nonAutoEnUS);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -631,9 +631,9 @@ public class InputMethodUtilsTest {
subtypes.add(nonAutoFil);
subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
final ArrayList<InputMethodSubtype> result =
InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
@@ -649,22 +649,22 @@ public class InputMethodUtilsTest {
@Test
public void testContainsSubtypeOf() throws Exception {
- final InputMethodSubtype nonAutoEnUS = createDummyInputMethodSubtype("en_US",
+ final InputMethodSubtype nonAutoEnUS = createFakeInputMethodSubtype("en_US",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoEnGB = createDummyInputMethodSubtype("en_GB",
+ final InputMethodSubtype nonAutoEnGB = createFakeInputMethodSubtype("en_GB",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoFil = createDummyInputMethodSubtype("fil",
+ final InputMethodSubtype nonAutoFil = createFakeInputMethodSubtype("fil",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoFilPH = createDummyInputMethodSubtype("fil_PH",
+ final InputMethodSubtype nonAutoFilPH = createFakeInputMethodSubtype("fil_PH",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoIn = createDummyInputMethodSubtype("in",
+ final InputMethodSubtype nonAutoIn = createFakeInputMethodSubtype("in",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
- final InputMethodSubtype nonAutoId = createDummyInputMethodSubtype("id",
+ final InputMethodSubtype nonAutoId = createFakeInputMethodSubtype("id",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
IS_ASCII_CAPABLE, IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
@@ -673,9 +673,9 @@ public class InputMethodUtilsTest {
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
subtypes.add(nonAutoEnUS);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_EN, !CHECK_COUNTRY,
@@ -705,9 +705,9 @@ public class InputMethodUtilsTest {
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
subtypes.add(nonAutoFil);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, !CHECK_COUNTRY,
SUBTYPE_MODE_KEYBOARD));
@@ -732,9 +732,9 @@ public class InputMethodUtilsTest {
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
subtypes.add(nonAutoFilPH);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_FIL, !CHECK_COUNTRY,
SUBTYPE_MODE_KEYBOARD));
@@ -760,9 +760,9 @@ public class InputMethodUtilsTest {
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
subtypes.add(nonAutoIn);
subtypes.add(nonAutoEnUS);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY,
SUBTYPE_MODE_KEYBOARD));
@@ -779,9 +779,9 @@ public class InputMethodUtilsTest {
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
subtypes.add(nonAutoId);
subtypes.add(nonAutoEnUS);
- final InputMethodInfo imi = createDummyInputMethodInfo(
+ final InputMethodInfo imi = createFakeInputMethodInfo(
"com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, IS_DEFAULT,
subtypes);
assertTrue(InputMethodUtils.containsSubtypeOf(imi, LOCALE_IN, !CHECK_COUNTRY,
SUBTYPE_MODE_KEYBOARD));
@@ -866,7 +866,7 @@ public class InputMethodUtilsTest {
assertEquals(expected.hashCode(), actual.hashCode());
}
- private static InputMethodInfo createDummyInputMethodInfo(String packageName, String name,
+ private static InputMethodInfo createFakeInputMethodInfo(String packageName, String name,
CharSequence label, boolean isAuxIme, boolean isDefault,
List<InputMethodSubtype> subtypes) {
final ResolveInfo ri = new ResolveInfo();
@@ -885,15 +885,15 @@ public class InputMethodUtilsTest {
return new InputMethodInfo(ri, isAuxIme, "", subtypes, 1, isDefault);
}
- private static InputMethodSubtype createDummyInputMethodSubtype(String locale, String mode,
+ private static InputMethodSubtype createFakeInputMethodSubtype(String locale, String mode,
boolean isAuxiliary, boolean overridesImplicitlyEnabledSubtype,
boolean isAsciiCapable, boolean isEnabledWhenDefaultIsNotAsciiCapable) {
- return createDummyInputMethodSubtype(locale, null /* languageTag */, mode, isAuxiliary,
+ return createFakeInputMethodSubtype(locale, null /* languageTag */, mode, isAuxiliary,
overridesImplicitlyEnabledSubtype, isAsciiCapable,
isEnabledWhenDefaultIsNotAsciiCapable);
}
- private static InputMethodSubtype createDummyInputMethodSubtype(String locale,
+ private static InputMethodSubtype createFakeInputMethodSubtype(String locale,
String languageTag, String mode, boolean isAuxiliary,
boolean overridesImplicitlyEnabledSubtype, boolean isAsciiCapable,
boolean isEnabledWhenDefaultIsNotAsciiCapable) {
@@ -920,14 +920,14 @@ public class InputMethodUtilsTest {
ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>();
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
- subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX,
IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- preinstalledImes.add(createDummyInputMethodInfo("DummyDefaultAutoVoiceIme",
- "dummy.voice0", "DummyVoice0", IS_AUX, IS_DEFAULT, subtypes));
+ preinstalledImes.add(createFakeInputMethodInfo("FakeDefaultAutoVoiceIme",
+ "fake.voice0", "FakeVoice0", IS_AUX, IS_DEFAULT, subtypes));
}
preinstalledImes.addAll(getImesWithoutDefaultVoiceIme());
return preinstalledImes;
@@ -937,41 +937,41 @@ public class InputMethodUtilsTest {
ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>();
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
- subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX,
IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme0",
- "dummy.voice1", "DummyVoice1", IS_AUX, !IS_DEFAULT, subtypes));
+ preinstalledImes.add(createFakeInputMethodInfo("FakeNonDefaultAutoVoiceIme0",
+ "fake.voice1", "FakeVoice1", IS_AUX, !IS_DEFAULT, subtypes));
}
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
- subtypes.add(createDummyInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("auto", SUBTYPE_MODE_VOICE, IS_AUX,
IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultAutoVoiceIme1",
- "dummy.voice2", "DummyVoice2", IS_AUX, !IS_DEFAULT, subtypes));
+ preinstalledImes.add(createFakeInputMethodInfo("FakeNonDefaultAutoVoiceIme1",
+ "fake.voice2", "FakeVoice2", IS_AUX, !IS_DEFAULT, subtypes));
}
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
- subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_VOICE, IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- preinstalledImes.add(createDummyInputMethodInfo("DummyNonDefaultVoiceIme2",
- "dummy.voice3", "DummyVoice3", IS_AUX, !IS_DEFAULT, subtypes));
+ preinstalledImes.add(createFakeInputMethodInfo("FakeNonDefaultVoiceIme2",
+ "fake.voice3", "FakeVoice3", IS_AUX, !IS_DEFAULT, subtypes));
}
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
- subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- preinstalledImes.add(createDummyInputMethodInfo("DummyDefaultEnKeyboardIme",
- "dummy.keyboard0", "DummyKeyboard0", !IS_AUX, IS_DEFAULT, subtypes));
+ preinstalledImes.add(createFakeInputMethodInfo("FakeDefaultEnKeyboardIme",
+ "fake.keyboard0", "FakeKeyboard0", !IS_AUX, IS_DEFAULT, subtypes));
}
return preinstalledImes;
}
@@ -991,91 +991,91 @@ public class InputMethodUtilsTest {
private static ArrayList<InputMethodInfo> getSamplePreinstalledImes(final String localeString) {
ArrayList<InputMethodInfo> preinstalledImes = new ArrayList<>();
- // a dummy Voice IME
+ // a fake Voice IME
{
final boolean isDefaultIme = false;
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
- subtypes.add(createDummyInputMethodSubtype("", SUBTYPE_MODE_VOICE, IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("", SUBTYPE_MODE_VOICE, IS_AUX,
IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.voice",
- "com.android.inputmethod.voice", "DummyVoiceIme", IS_AUX, isDefaultIme,
+ preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.voice",
+ "com.android.inputmethod.voice", "FakeVoiceIme", IS_AUX, isDefaultIme,
subtypes));
}
- // a dummy Hindi IME
+ // a fake Hindi IME
{
final boolean isDefaultIme = contains(new String[]{ "hi", "en-rIN" }, localeString);
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
// TODO: This subtype should be marked as IS_ASCII_CAPABLE
- subtypes.add(createDummyInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- subtypes.add(createDummyInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.hindi",
- "com.android.inputmethod.hindi", "DummyHindiIme", !IS_AUX, isDefaultIme,
+ preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.hindi",
+ "com.android.inputmethod.hindi", "FakeHindiIme", !IS_AUX, isDefaultIme,
subtypes));
}
- // a dummy Pinyin IME
+ // a fake Pinyin IME
{
final boolean isDefaultIme = contains(new String[]{ "zh-rCN" }, localeString);
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
- subtypes.add(createDummyInputMethodSubtype("zh_CN", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("zh_CN", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.pinyin",
- "com.android.apps.inputmethod.pinyin", "DummyPinyinIme", !IS_AUX, isDefaultIme,
+ preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.pinyin",
+ "com.android.apps.inputmethod.pinyin", "FakePinyinIme", !IS_AUX, isDefaultIme,
subtypes));
}
- // a dummy Korean IME
+ // a fake Korean IME
{
final boolean isDefaultIme = contains(new String[]{ "ko" }, localeString);
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
- subtypes.add(createDummyInputMethodSubtype("ko", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("ko", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.korean",
- "com.android.apps.inputmethod.korean", "DummyKoreanIme", !IS_AUX, isDefaultIme,
+ preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.korean",
+ "com.android.apps.inputmethod.korean", "FakeKoreanIme", !IS_AUX, isDefaultIme,
subtypes));
}
- // a dummy Latin IME
+ // a fake Latin IME
{
final boolean isDefaultIme = contains(
new String[]{ "en-rUS", "en-rGB", "en-rIN", "en", "hi" }, localeString);
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
- subtypes.add(createDummyInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("en_US", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- subtypes.add(createDummyInputMethodSubtype("en_GB", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("en_GB", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- subtypes.add(createDummyInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("en_IN", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- subtypes.add(createDummyInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("hi", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.latin",
- "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, isDefaultIme,
+ preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "FakeLatinIme", !IS_AUX, isDefaultIme,
subtypes));
}
- // a dummy Japanese IME
+ // a fake Japanese IME
{
final boolean isDefaultIme = contains(new String[]{ "ja", "ja-rJP" }, localeString);
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
- subtypes.add(createDummyInputMethodSubtype("ja", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("ja", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- subtypes.add(createDummyInputMethodSubtype("emoji", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
+ subtypes.add(createFakeInputMethodSubtype("emoji", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
!IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE));
- preinstalledImes.add(createDummyInputMethodInfo("com.android.apps.inputmethod.japanese",
- "com.android.apps.inputmethod.japanese", "DummyJapaneseIme", !IS_AUX,
+ preinstalledImes.add(createFakeInputMethodInfo("com.android.apps.inputmethod.japanese",
+ "com.android.apps.inputmethod.japanese", "FakeJapaneseIme", !IS_AUX,
isDefaultIme, subtypes));
}
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 128177b073b0..58b71d4b702a 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -462,7 +462,7 @@ public class NetworkPolicyManagerServiceTest {
@Test
public void testTurnRestrictBackgroundOn() throws Exception {
- assertRestrictBackgroundOff(); // Sanity check.
+ assertRestrictBackgroundOff();
final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
setRestrictBackground(true);
assertRestrictBackgroundChangedReceived(futureIntent, null);
@@ -471,7 +471,7 @@ public class NetworkPolicyManagerServiceTest {
@Test
@NetPolicyXml("restrict-background-on.xml")
public void testTurnRestrictBackgroundOff() throws Exception {
- assertRestrictBackgroundOn(); // Sanity check.
+ assertRestrictBackgroundOn();
assertRestrictBackgroundChangedReceived(mFutureIntent, null);
final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
setRestrictBackground(false);
@@ -479,28 +479,27 @@ public class NetworkPolicyManagerServiceTest {
}
/**
- * Adds whitelist when restrict background is on - app should receive an intent.
+ * Adds allowlist when restrict background is on - app should receive an intent.
*/
@Test
@NetPolicyXml("restrict-background-on.xml")
- public void testAddRestrictBackgroundWhitelist_restrictBackgroundOn() throws Exception {
- assertRestrictBackgroundOn(); // Sanity check.
+ public void testAddRestrictBackgroundAllowlist_restrictBackgroundOn() throws Exception {
+ assertRestrictBackgroundOn();
assertRestrictBackgroundChangedReceived(mFutureIntent, null);
- addRestrictBackgroundWhitelist(true);
+ addRestrictBackgroundAllowlist(true);
}
/**
- * Adds whitelist when restrict background is off - app should not receive an intent.
+ * Adds allowlist when restrict background is off - app should not receive an intent.
*/
@Test
- public void testAddRestrictBackgroundWhitelist_restrictBackgroundOff() throws Exception {
- assertRestrictBackgroundOff(); // Sanity check.
- addRestrictBackgroundWhitelist(false);
+ public void testAddRestrictBackgroundAllowlist_restrictBackgroundOff() throws Exception {
+ assertRestrictBackgroundOff();
+ addRestrictBackgroundAllowlist(false);
}
- private void addRestrictBackgroundWhitelist(boolean expectIntent) throws Exception {
- // Sanity checks.
- assertWhitelistUids();
+ private void addRestrictBackgroundAllowlist(boolean expectIntent) throws Exception {
+ assertAllowlistUids();
assertUidPolicy(UID_A, POLICY_NONE);
final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
@@ -508,7 +507,7 @@ public class NetworkPolicyManagerServiceTest {
mService.setUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND);
- assertWhitelistUids(UID_A);
+ assertAllowlistUids(UID_A);
assertUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND);
mPolicyListener.waitAndVerify()
.onUidPoliciesChanged(APP_ID_A, POLICY_ALLOW_METERED_BACKGROUND);
@@ -520,24 +519,24 @@ public class NetworkPolicyManagerServiceTest {
}
/**
- * Removes whitelist when restrict background is on - app should receive an intent.
+ * Removes allowlist when restrict background is on - app should receive an intent.
*/
@Test
- @NetPolicyXml("uidA-whitelisted-restrict-background-on.xml")
- public void testRemoveRestrictBackgroundWhitelist_restrictBackgroundOn() throws Exception {
- assertRestrictBackgroundOn(); // Sanity check.
+ @NetPolicyXml("uidA-allowlisted-restrict-background-on.xml")
+ public void testRemoveRestrictBackgroundAllowlist_restrictBackgroundOn() throws Exception {
+ assertRestrictBackgroundOn();
assertRestrictBackgroundChangedReceived(mFutureIntent, null);
- removeRestrictBackgroundWhitelist(true);
+ removeRestrictBackgroundAllowlist(true);
}
/**
- * Removes whitelist when restrict background is off - app should not receive an intent.
+ * Removes allowlist when restrict background is off - app should not receive an intent.
*/
@Test
- @NetPolicyXml("uidA-whitelisted-restrict-background-off.xml")
- public void testRemoveRestrictBackgroundWhitelist_restrictBackgroundOff() throws Exception {
- assertRestrictBackgroundOff(); // Sanity check.
- removeRestrictBackgroundWhitelist(false);
+ @NetPolicyXml("uidA-allowlisted-restrict-background-off.xml")
+ public void testRemoveRestrictBackgroundAllowlist_restrictBackgroundOff() throws Exception {
+ assertRestrictBackgroundOff();
+ removeRestrictBackgroundAllowlist(false);
}
@Test
@@ -688,9 +687,8 @@ public class NetworkPolicyManagerServiceTest {
assertFalse(mService.getRestrictBackground());
}
- private void removeRestrictBackgroundWhitelist(boolean expectIntent) throws Exception {
- // Sanity checks.
- assertWhitelistUids(UID_A);
+ private void removeRestrictBackgroundAllowlist(boolean expectIntent) throws Exception {
+ assertAllowlistUids(UID_A);
assertUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND);
final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
@@ -698,7 +696,7 @@ public class NetworkPolicyManagerServiceTest {
mService.setUidPolicy(UID_A, POLICY_NONE);
- assertWhitelistUids();
+ assertAllowlistUids();
assertUidPolicy(UID_A, POLICY_NONE);
mPolicyListener.waitAndVerify().onUidPoliciesChanged(APP_ID_A, POLICY_NONE);
if (expectIntent) {
@@ -709,27 +707,27 @@ public class NetworkPolicyManagerServiceTest {
}
/**
- * Adds blacklist when restrict background is on - app should not receive an intent.
+ * Adds denylist when restrict background is on - app should not receive an intent.
*/
@Test
@NetPolicyXml("restrict-background-on.xml")
- public void testAddRestrictBackgroundBlacklist_restrictBackgroundOn() throws Exception {
- assertRestrictBackgroundOn(); // Sanity check.
+ public void testAddRestrictBackgroundDenylist_restrictBackgroundOn() throws Exception {
+ assertRestrictBackgroundOn();
assertRestrictBackgroundChangedReceived(mFutureIntent, null);
- addRestrictBackgroundBlacklist(false);
+ addRestrictBackgroundDenylist(false);
}
/**
- * Adds blacklist when restrict background is off - app should receive an intent.
+ * Adds denylist when restrict background is off - app should receive an intent.
*/
@Test
- public void testAddRestrictBackgroundBlacklist_restrictBackgroundOff() throws Exception {
- assertRestrictBackgroundOff(); // Sanity check.
- addRestrictBackgroundBlacklist(true);
+ public void testAddRestrictBackgroundDenylist_restrictBackgroundOff() throws Exception {
+ assertRestrictBackgroundOff();
+ addRestrictBackgroundDenylist(true);
}
- private void addRestrictBackgroundBlacklist(boolean expectIntent) throws Exception {
- assertUidPolicy(UID_A, POLICY_NONE); // Sanity check.
+ private void addRestrictBackgroundDenylist(boolean expectIntent) throws Exception {
+ assertUidPolicy(UID_A, POLICY_NONE);
final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
mPolicyListener.expect().onUidPoliciesChanged(anyInt(), anyInt());
@@ -746,28 +744,28 @@ public class NetworkPolicyManagerServiceTest {
}
/**
- * Removes blacklist when restrict background is on - app should not receive an intent.
+ * Removes denylist when restrict background is on - app should not receive an intent.
*/
@Test
- @NetPolicyXml("uidA-blacklisted-restrict-background-on.xml")
- public void testRemoveRestrictBackgroundBlacklist_restrictBackgroundOn() throws Exception {
- assertRestrictBackgroundOn(); // Sanity check.
+ @NetPolicyXml("uidA-denylisted-restrict-background-on.xml")
+ public void testRemoveRestrictBackgroundDenylist_restrictBackgroundOn() throws Exception {
+ assertRestrictBackgroundOn();
assertRestrictBackgroundChangedReceived(mFutureIntent, null);
- removeRestrictBackgroundBlacklist(false);
+ removeRestrictBackgroundDenylist(false);
}
/**
- * Removes blacklist when restrict background is off - app should receive an intent.
+ * Removes denylist when restrict background is off - app should receive an intent.
*/
@Test
- @NetPolicyXml("uidA-blacklisted-restrict-background-off.xml")
- public void testRemoveRestrictBackgroundBlacklist_restrictBackgroundOff() throws Exception {
- assertRestrictBackgroundOff(); // Sanity check.
- removeRestrictBackgroundBlacklist(true);
+ @NetPolicyXml("uidA-denylisted-restrict-background-off.xml")
+ public void testRemoveRestrictBackgroundDenylist_restrictBackgroundOff() throws Exception {
+ assertRestrictBackgroundOff();
+ removeRestrictBackgroundDenylist(true);
}
- private void removeRestrictBackgroundBlacklist(boolean expectIntent) throws Exception {
- assertUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND); // Sanity check.
+ private void removeRestrictBackgroundDenylist(boolean expectIntent) throws Exception {
+ assertUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
mPolicyListener.expect().onUidPoliciesChanged(anyInt(), anyInt());
@@ -784,9 +782,8 @@ public class NetworkPolicyManagerServiceTest {
}
@Test
- @NetPolicyXml("uidA-blacklisted-restrict-background-on.xml")
- public void testBlacklistedAppIsNotNotifiedWhenRestrictBackgroundIsOn() throws Exception {
- // Sanity checks.
+ @NetPolicyXml("uidA-denylisted-restrict-background-on.xml")
+ public void testDenylistedAppIsNotNotifiedWhenRestrictBackgroundIsOn() throws Exception {
assertRestrictBackgroundOn();
assertRestrictBackgroundChangedReceived(mFutureIntent, null);
assertUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
@@ -797,12 +794,11 @@ public class NetworkPolicyManagerServiceTest {
}
@Test
- @NetPolicyXml("uidA-whitelisted-restrict-background-on.xml")
- public void testWhitelistedAppIsNotNotifiedWhenRestrictBackgroundIsOn() throws Exception {
- // Sanity checks.
+ @NetPolicyXml("uidA-allowlisted-restrict-background-on.xml")
+ public void testAllowlistedAppIsNotNotifiedWhenRestrictBackgroundIsOn() throws Exception {
assertRestrictBackgroundOn();
assertRestrictBackgroundChangedReceived(mFutureIntent, null);
- assertWhitelistUids(UID_A);
+ assertAllowlistUids(UID_A);
final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
setRestrictBackground(true);
@@ -810,12 +806,11 @@ public class NetworkPolicyManagerServiceTest {
}
@Test
- @NetPolicyXml("uidA-whitelisted-restrict-background-on.xml")
- public void testWhitelistedAppIsNotifiedWhenBlacklisted() throws Exception {
- // Sanity checks.
+ @NetPolicyXml("uidA-allowlisted-restrict-background-on.xml")
+ public void testAllowlistedAppIsNotifiedWhenDenylisted() throws Exception {
assertRestrictBackgroundOn();
assertRestrictBackgroundChangedReceived(mFutureIntent, null);
- assertWhitelistUids(UID_A);
+ assertAllowlistUids(UID_A);
final FutureIntent futureIntent = newRestrictBackgroundChangedFuture();
mService.setUidPolicy(UID_A, POLICY_REJECT_METERED_BACKGROUND);
@@ -823,8 +818,8 @@ public class NetworkPolicyManagerServiceTest {
}
@Test
- @NetPolicyXml("restrict-background-lists-whitelist-format.xml")
- public void testRestrictBackgroundLists_whitelistFormat() throws Exception {
+ @NetPolicyXml("restrict-background-lists-allowlist-format.xml")
+ public void testRestrictBackgroundLists_allowlistFormat() throws Exception {
restrictBackgroundListsTest();
}
@@ -835,33 +830,33 @@ public class NetworkPolicyManagerServiceTest {
}
private void restrictBackgroundListsTest() throws Exception {
- // UIds that are whitelisted.
- assertWhitelistUids(UID_A, UID_B, UID_C);
+ // UIds that are allowlisted.
+ assertAllowlistUids(UID_A, UID_B, UID_C);
assertUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND);
assertUidPolicy(UID_B, POLICY_ALLOW_METERED_BACKGROUND);
assertUidPolicy(UID_C, POLICY_ALLOW_METERED_BACKGROUND);
- // UIDs that are blacklisted.
+ // UIDs that are denylisted.
assertUidPolicy(UID_D, POLICY_NONE);
assertUidPolicy(UID_E, POLICY_REJECT_METERED_BACKGROUND);
// UIDS that have legacy policies.
assertUidPolicy(UID_F, 2); // POLICY_ALLOW_BACKGROUND_BATTERY_SAVE
- // Remove whitelist.
+ // Remove allowlist.
mService.setUidPolicy(UID_A, POLICY_NONE);
assertUidPolicy(UID_A, POLICY_NONE);
- assertWhitelistUids(UID_B, UID_C);
+ assertAllowlistUids(UID_B, UID_C);
- // Add whitelist when blacklisted.
+ // Add allowlist when denylisted.
mService.setUidPolicy(UID_E, POLICY_ALLOW_METERED_BACKGROUND);
assertUidPolicy(UID_E, POLICY_ALLOW_METERED_BACKGROUND);
- assertWhitelistUids(UID_B, UID_C, UID_E);
+ assertAllowlistUids(UID_B, UID_C, UID_E);
- // Add blacklist when whitelisted.
+ // Add denylist when allowlisted.
mService.setUidPolicy(UID_B, POLICY_REJECT_METERED_BACKGROUND);
assertUidPolicy(UID_B, POLICY_REJECT_METERED_BACKGROUND);
- assertWhitelistUids(UID_C, UID_E);
+ assertAllowlistUids(UID_C, UID_E);
}
/**
@@ -870,9 +865,9 @@ public class NetworkPolicyManagerServiceTest {
@Test
@NetPolicyXml("restrict-background-lists-mixed-format.xml")
public void testRestrictBackgroundLists_mixedFormat() throws Exception {
- assertWhitelistUids(UID_A, UID_C, UID_D);
+ assertAllowlistUids(UID_A, UID_C, UID_D);
assertUidPolicy(UID_A, POLICY_ALLOW_METERED_BACKGROUND);
- assertUidPolicy(UID_B, POLICY_REJECT_METERED_BACKGROUND); // Blacklist prevails.
+ assertUidPolicy(UID_B, POLICY_REJECT_METERED_BACKGROUND); // Denylist prevails.
assertUidPolicy(UID_C, (POLICY_ALLOW_METERED_BACKGROUND | 2));
assertUidPolicy(UID_D, POLICY_ALLOW_METERED_BACKGROUND);
}
@@ -2045,7 +2040,7 @@ public class NetworkPolicyManagerServiceTest {
}
}
- private void assertWhitelistUids(int... uids) {
+ private void assertAllowlistUids(int... uids) {
assertContainsInAnyOrder(mService.getUidsWithPolicy(POLICY_ALLOW_METERED_BACKGROUND), uids);
}
@@ -2133,7 +2128,6 @@ public class NetworkPolicyManagerServiceTest {
private void setRestrictBackground(boolean flag) throws Exception {
mService.setRestrictBackground(flag);
- // Sanity check.
assertEquals("restrictBackground not set", flag, mService.getRestrictBackground());
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
index 80f145b16147..35d6f470a504 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -48,7 +48,7 @@ public class PackageManagerServiceTest {
public void sendPackageBroadcast(final String action, final String pkg,
final Bundle extras, final int flags, final String targetPkg,
final IIntentReceiver finishedReceiver, final int[] userIds,
- int[] instantUserIds, SparseArray<int[]> broadcastWhitelist) {
+ int[] instantUserIds, SparseArray<int[]> broadcastAllowList) {
}
public void sendPackageAddedForNewUsers(String packageName,
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt
index 9f9ec31f0c91..f96ebda67602 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt
@@ -23,6 +23,8 @@ import com.google.common.truth.Expect
import org.junit.Rule
import org.junit.Test
+import org.junit.rules.Timeout
+import java.util.concurrent.TimeUnit
/**
* Collects APKs from the device and verifies that the new parsing behavior outputs
@@ -32,6 +34,9 @@ import org.junit.Test
class AndroidPackageParsingEquivalenceTest : AndroidPackageParsingTestBase() {
@get:Rule
+ val timeout = Timeout(4, TimeUnit.MINUTES)
+
+ @get:Rule
val expect = Expect.create()
@Test
diff --git a/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java
index 083df28b2278..aaa74dd832af 100644
--- a/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java
@@ -284,28 +284,29 @@ public class ThermalManagerServiceTest {
@Test
public void testNotify() throws RemoteException {
int status = Temperature.THROTTLING_SEVERE;
+ // Should only notify event not status
Temperature newBattery = new Temperature(50, Temperature.TYPE_BATTERY, "batt", status);
mFakeHal.mCallback.onValues(newBattery);
verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
.times(1)).notifyThrottling(newBattery);
verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
- .times(1)).onStatusChange(status);
+ .times(0)).onStatusChange(anyInt());
verify(mEventListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
.times(0)).notifyThrottling(newBattery);
verify(mStatusListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
- .times(1)).onStatusChange(status);
+ .times(0)).onStatusChange(anyInt());
resetListenerMock();
- // Should only notify event not status
+ // Notify both event and status
Temperature newSkin = new Temperature(50, Temperature.TYPE_SKIN, "skin1", status);
mFakeHal.mCallback.onValues(newSkin);
verify(mEventListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
.times(1)).notifyThrottling(newSkin);
verify(mStatusListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
- .times(0)).onStatusChange(anyInt());
+ .times(1)).onStatusChange(status);
verify(mEventListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
.times(1)).notifyThrottling(newSkin);
verify(mStatusListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
- .times(0)).onStatusChange(anyInt());
+ .times(1)).onStatusChange(status);
resetListenerMock();
// Back to None, should only notify event not status
status = Temperature.THROTTLING_NONE;
@@ -345,10 +346,13 @@ public class ThermalManagerServiceTest {
@Test
public void testGetCurrentStatus() throws RemoteException {
- int status = Temperature.THROTTLING_EMERGENCY;
+ int status = Temperature.THROTTLING_SEVERE;
Temperature newSkin = new Temperature(100, Temperature.TYPE_SKIN, "skin1", status);
mFakeHal.mCallback.onValues(newSkin);
assertEquals(status, mService.mService.getCurrentThermalStatus());
+ int battStatus = Temperature.THROTTLING_EMERGENCY;
+ Temperature newBattery = new Temperature(60, Temperature.TYPE_BATTERY, "batt", battStatus);
+ assertEquals(status, mService.mService.getCurrentThermalStatus());
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java
index dcf319058ca2..e5e931115c05 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java
@@ -27,6 +27,9 @@ import android.app.timezonedetector.TimeZoneCapabilities;
import android.app.timezonedetector.TimeZoneConfiguration;
import android.util.IndentingPrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
private StrategyListener mListener;
@@ -41,6 +44,7 @@ class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
private TelephonyTimeZoneSuggestion mLastTelephonySuggestion;
private boolean mHandleAutoTimeZoneConfigChangedCalled;
private boolean mDumpCalled;
+ private final List<Dumpable> mDumpables = new ArrayList<>();
@Override
public void setStrategyListener(@NonNull StrategyListener listener) {
@@ -105,7 +109,7 @@ class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
@Override
public void addDumpable(Dumpable dumpable) {
- // Stubbed
+ mDumpables.add(dumpable);
}
@Override
@@ -149,4 +153,8 @@ class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
void verifyDumpCalled() {
assertTrue(mDumpCalled);
}
+
+ void verifyHasDumpable(Dumpable expected) {
+ assertTrue(mDumpables.contains(expected));
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java
index 0e2c22756097..e9d57e52ce69 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java
@@ -75,6 +75,16 @@ public class TimeZoneDetectorInternalImplTest {
mFakeTimeZoneDetectorStrategy.verifySuggestGeolocationTimeZoneCalled(timeZoneSuggestion);
}
+ @Test
+ public void testAddDumpable() throws Exception {
+ Dumpable stubbedDumpable = mock(Dumpable.class);
+
+ mTimeZoneDetectorInternal.addDumpable(stubbedDumpable);
+ mTestHandler.assertTotalMessagesEnqueued(0);
+
+ mFakeTimeZoneDetectorStrategy.verifyHasDumpable(stubbedDumpable);
+ }
+
private static GeolocationTimeZoneSuggestion createGeolocationTimeZoneSuggestion() {
return new GeolocationTimeZoneSuggestion(ARBITRARY_ZONE_IDS);
}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
index 8034cacc6923..3a1ec4f90d7a 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
@@ -52,6 +52,7 @@ import org.junit.runner.RunWith;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.util.Arrays;
@RunWith(AndroidJUnit4.class)
public class TimeZoneDetectorServiceTest {
@@ -253,6 +254,39 @@ public class TimeZoneDetectorServiceTest {
}
@Test(expected = SecurityException.class)
+ public void testSuggestGeolocationTimeZone_withoutPermission() {
+ doThrow(new SecurityException("Mock"))
+ .when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
+ GeolocationTimeZoneSuggestion timeZoneSuggestion = createGeolocationTimeZoneSuggestion();
+
+ try {
+ mTimeZoneDetectorService.suggestGeolocationTimeZone(timeZoneSuggestion);
+ fail();
+ } finally {
+ verify(mMockContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.SET_TIME_ZONE),
+ anyString());
+ }
+ }
+
+ @Test
+ public void testSuggestGeolocationTimeZone() throws Exception {
+ doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
+
+ GeolocationTimeZoneSuggestion timeZoneSuggestion = createGeolocationTimeZoneSuggestion();
+
+ mTimeZoneDetectorService.suggestGeolocationTimeZone(timeZoneSuggestion);
+ mTestHandler.assertTotalMessagesEnqueued(1);
+
+ verify(mMockContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.SET_TIME_ZONE),
+ anyString());
+
+ mTestHandler.waitForMessagesToBeProcessed();
+ mFakeTimeZoneDetectorStrategy.verifySuggestGeolocationTimeZoneCalled(timeZoneSuggestion);
+ }
+
+ @Test(expected = SecurityException.class)
public void testSuggestManualTimeZone_withoutPermission() {
doThrow(new SecurityException("Mock"))
.when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
@@ -346,7 +380,7 @@ public class TimeZoneDetectorServiceTest {
}
@Test
- public void testAutoTimeZoneDetectionChanged() throws Exception {
+ public void testHandleAutoTimeZoneConfigChanged() throws Exception {
mTimeZoneDetectorService.handleAutoTimeZoneConfigChanged();
mTestHandler.assertTotalMessagesEnqueued(1);
mTestHandler.waitForMessagesToBeProcessed();
@@ -370,10 +404,15 @@ public class TimeZoneDetectorServiceTest {
private static TimeZoneCapabilities createTimeZoneCapabilities() {
return new TimeZoneCapabilities.Builder(ARBITRARY_USER_ID)
.setConfigureAutoDetectionEnabled(CAPABILITY_POSSESSED)
+ .setConfigureGeoDetectionEnabled(CAPABILITY_POSSESSED)
.setSuggestManualTimeZone(CAPABILITY_POSSESSED)
.build();
}
+ private static GeolocationTimeZoneSuggestion createGeolocationTimeZoneSuggestion() {
+ return new GeolocationTimeZoneSuggestion(Arrays.asList("TestZoneId"));
+ }
+
private static ManualTimeZoneSuggestion createManualTimeZoneSuggestion() {
return new ManualTimeZoneSuggestion("TestZoneId");
}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
index 68554451e43a..a6caa4299ef6 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
@@ -41,6 +41,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.timezonedetector.ManualTimeZoneSuggestion;
import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
@@ -56,10 +57,10 @@ import org.junit.Before;
import org.junit.Test;
import java.io.StringWriter;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
+import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -93,16 +94,26 @@ public class TimeZoneDetectorStrategyImplTest {
TELEPHONY_SCORE_HIGHEST),
};
- private static final TimeZoneConfiguration CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED =
+ private static final TimeZoneConfiguration CONFIG_AUTO_ENABLED =
new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(true)
.build();
- private static final TimeZoneConfiguration CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED =
+ private static final TimeZoneConfiguration CONFIG_AUTO_DISABLED =
new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(false)
.build();
+ private static final TimeZoneConfiguration CONFIG_GEO_DETECTION_DISABLED =
+ new TimeZoneConfiguration.Builder()
+ .setGeoDetectionEnabled(false)
+ .build();
+
+ private static final TimeZoneConfiguration CONFIG_GEO_DETECTION_ENABLED =
+ new TimeZoneConfiguration.Builder()
+ .setGeoDetectionEnabled(true)
+ .build();
+
private TimeZoneDetectorStrategyImpl mTimeZoneDetectorStrategy;
private FakeCallback mFakeCallback;
private MockStrategyListener mMockStrategyListener;
@@ -120,7 +131,7 @@ public class TimeZoneDetectorStrategyImplTest {
public void testGetCapabilities() {
new Script()
.initializeUser(USER_ID, UserCase.UNRESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED);
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED));
TimeZoneCapabilities expectedCapabilities = mFakeCallback.getCapabilities(USER_ID);
assertEquals(expectedCapabilities, mTimeZoneDetectorStrategy.getCapabilities(USER_ID));
}
@@ -129,7 +140,7 @@ public class TimeZoneDetectorStrategyImplTest {
public void testGetConfiguration() {
new Script()
.initializeUser(USER_ID, UserCase.UNRESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED);
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED));
TimeZoneConfiguration expectedConfiguration = mFakeCallback.getConfiguration(USER_ID);
assertTrue(expectedConfiguration.isComplete());
assertEquals(expectedConfiguration, mTimeZoneDetectorStrategy.getConfiguration(USER_ID));
@@ -140,20 +151,22 @@ public class TimeZoneDetectorStrategyImplTest {
Script script = new Script();
script.initializeUser(USER_ID, UserCase.UNRESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED);
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED));
{
// Check the fake test infra is doing what is expected.
TimeZoneCapabilities capabilities = mFakeCallback.getCapabilities(USER_ID);
assertEquals(CAPABILITY_POSSESSED, capabilities.getConfigureAutoDetectionEnabled());
+ assertEquals(CAPABILITY_POSSESSED, capabilities.getConfigureGeoDetectionEnabled());
assertEquals(CAPABILITY_NOT_APPLICABLE, capabilities.getSuggestManualTimeZone());
}
script.initializeUser(USER_ID, UserCase.UNRESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED);
+ CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED));
{
// Check the fake test infra is doing what is expected.
TimeZoneCapabilities capabilities = mFakeCallback.getCapabilities(USER_ID);
assertEquals(CAPABILITY_POSSESSED, capabilities.getConfigureAutoDetectionEnabled());
+ assertEquals(CAPABILITY_POSSESSED, capabilities.getConfigureGeoDetectionEnabled());
assertEquals(CAPABILITY_POSSESSED, capabilities.getSuggestManualTimeZone());
}
}
@@ -163,20 +176,22 @@ public class TimeZoneDetectorStrategyImplTest {
Script script = new Script();
script.initializeUser(USER_ID, UserCase.RESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED);
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED));
{
// Check the fake test infra is doing what is expected.
TimeZoneCapabilities capabilities = mFakeCallback.getCapabilities(USER_ID);
assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getConfigureAutoDetectionEnabled());
+ assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getConfigureGeoDetectionEnabled());
assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSuggestManualTimeZone());
}
script.initializeUser(USER_ID, UserCase.RESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED);
+ CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED));
{
// Check the fake test infra is doing what is expected.
TimeZoneCapabilities capabilities = mFakeCallback.getCapabilities(USER_ID);
assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getConfigureAutoDetectionEnabled());
+ assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getConfigureGeoDetectionEnabled());
assertEquals(CAPABILITY_NOT_ALLOWED, capabilities.getSuggestManualTimeZone());
}
}
@@ -186,20 +201,22 @@ public class TimeZoneDetectorStrategyImplTest {
Script script = new Script();
script.initializeUser(USER_ID, UserCase.AUTO_DETECT_NOT_SUPPORTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED);
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED));
{
// Check the fake test infra is doing what is expected.
TimeZoneCapabilities capabilities = mFakeCallback.getCapabilities(USER_ID);
assertEquals(CAPABILITY_NOT_SUPPORTED, capabilities.getConfigureAutoDetectionEnabled());
+ assertEquals(CAPABILITY_NOT_SUPPORTED, capabilities.getConfigureGeoDetectionEnabled());
assertEquals(CAPABILITY_POSSESSED, capabilities.getSuggestManualTimeZone());
}
script.initializeUser(USER_ID, UserCase.AUTO_DETECT_NOT_SUPPORTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED);
+ CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED));
{
// Check the fake test infra is doing what is expected.
TimeZoneCapabilities capabilities = mFakeCallback.getCapabilities(USER_ID);
assertEquals(CAPABILITY_NOT_SUPPORTED, capabilities.getConfigureAutoDetectionEnabled());
+ assertEquals(CAPABILITY_NOT_SUPPORTED, capabilities.getConfigureGeoDetectionEnabled());
assertEquals(CAPABILITY_POSSESSED, capabilities.getSuggestManualTimeZone());
}
}
@@ -208,42 +225,61 @@ public class TimeZoneDetectorStrategyImplTest {
public void testUpdateConfiguration_unrestricted() {
Script script = new Script()
.initializeUser(USER_ID, UserCase.UNRESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED);
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED));
// Set the configuration with auto detection enabled.
- script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED);
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */);
// Nothing should have happened: it was initialized in this state.
script.verifyConfigurationNotChanged();
// Update the configuration with auto detection disabled.
- script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED);
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */);
// The settings should have been changed and the StrategyListener onChange() called.
- script.verifyConfigurationChangedAndReset(
- USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED);
+ script.verifyConfigurationChangedAndReset(USER_ID,
+ CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED));
// Update the configuration with auto detection enabled.
- script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED);
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */);
// The settings should have been changed and the StrategyListener onChange() called.
- script.verifyConfigurationChangedAndReset(USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED);
+ script.verifyConfigurationChangedAndReset(USER_ID,
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED));
+
+ // Update the configuration to enable geolocation time zone detection.
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_GEO_DETECTION_ENABLED, true /* expectedResult */);
+
+ // The settings should have been changed and the StrategyListener onChange() called.
+ script.verifyConfigurationChangedAndReset(USER_ID,
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_ENABLED));
}
@Test
public void testUpdateConfiguration_restricted() {
Script script = new Script()
.initializeUser(USER_ID, UserCase.RESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED);
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED));
// Try to update the configuration with auto detection disabled.
- script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED);
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_DISABLED, false /* expectedResult */);
// The settings should not have been changed: user shouldn't have the capabilities.
script.verifyConfigurationNotChanged();
// Update the configuration with auto detection enabled.
- script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED);
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_ENABLED, false /* expectedResult */);
+
+ // The settings should not have been changed: user shouldn't have the capabilities.
+ script.verifyConfigurationNotChanged();
+
+ // Update the configuration to enable geolocation time zone detection.
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_GEO_DETECTION_ENABLED, false /* expectedResult */);
// The settings should not have been changed: user shouldn't have the capabilities.
script.verifyConfigurationNotChanged();
@@ -253,16 +289,18 @@ public class TimeZoneDetectorStrategyImplTest {
public void testUpdateConfiguration_autoDetectNotSupported() {
Script script = new Script()
.initializeUser(USER_ID, UserCase.AUTO_DETECT_NOT_SUPPORTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED);
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED));
// Try to update the configuration with auto detection disabled.
- script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED);
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_DISABLED, false /* expectedResult */);
// The settings should not have been changed: user shouldn't have the capabilities.
script.verifyConfigurationNotChanged();
// Update the configuration with auto detection enabled.
- script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED);
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_ENABLED, false /* expectedResult */);
// The settings should not have been changed: user shouldn't have the capabilities.
script.verifyConfigurationNotChanged();
@@ -276,7 +314,7 @@ public class TimeZoneDetectorStrategyImplTest {
createEmptySlotIndex2Suggestion();
Script script = new Script()
.initializeUser(USER_ID, UserCase.UNRESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED)
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED))
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
script.simulateTelephonyTimeZoneSuggestion(slotIndex1TimeZoneSuggestion)
@@ -308,6 +346,10 @@ public class TimeZoneDetectorStrategyImplTest {
mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
}
+ /**
+ * Telephony suggestions have quality metadata. Ordinarily, low scoring suggestions are not
+ * used, but this is not true if the device's time zone setting is uninitialized.
+ */
@Test
public void testTelephonySuggestionsWhenTimeZoneUninitialized() {
assertTrue(TELEPHONY_SCORE_LOW < TELEPHONY_SCORE_USAGE_THRESHOLD);
@@ -319,7 +361,7 @@ public class TimeZoneDetectorStrategyImplTest {
Script script = new Script()
.initializeUser(USER_ID, UserCase.UNRESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED);
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED));
// A low quality suggestions will not be taken: The device time zone setting is left
// uninitialized.
@@ -376,16 +418,16 @@ public class TimeZoneDetectorStrategyImplTest {
/**
* Confirms that toggling the auto time zone detection setting has the expected behavior when
- * the strategy is "opinionated".
+ * the strategy is "opinionated" when using telephony auto detection.
*/
@Test
- public void testTogglingAutoTimeZoneDetection() {
+ public void testTogglingAutoDetection_autoTelephony() {
Script script = new Script();
for (TelephonyTestCase testCase : TELEPHONY_TEST_CASES) {
// Start with the device in a known state.
script.initializeUser(USER_ID, UserCase.UNRESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED)
+ CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED))
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
TelephonyTimeZoneSuggestion suggestion =
@@ -405,7 +447,8 @@ public class TimeZoneDetectorStrategyImplTest {
mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
// Toggling the time zone setting on should cause the device setting to be set.
- script.simulateAutoTimeZoneDetectionEnabled(USER_ID, true);
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED,
+ true /* expectedResult */);
// When time zone detection is already enabled the suggestion (if it scores highly
// enough) should be set immediately.
@@ -422,7 +465,8 @@ public class TimeZoneDetectorStrategyImplTest {
mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
// Toggling the time zone setting should off should do nothing.
- script.simulateAutoTimeZoneDetectionEnabled(USER_ID, false)
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */)
.verifyTimeZoneNotChanged();
// Assert internal service state.
@@ -437,7 +481,7 @@ public class TimeZoneDetectorStrategyImplTest {
public void testTelephonySuggestionsSingleSlotId() {
Script script = new Script()
.initializeUser(USER_ID, UserCase.UNRESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED)
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED))
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
for (TelephonyTestCase testCase : TELEPHONY_TEST_CASES) {
@@ -451,8 +495,7 @@ public class TimeZoneDetectorStrategyImplTest {
*/
// Each test case will have the same or lower score than the last.
- ArrayList<TelephonyTestCase> descendingCasesByScore =
- new ArrayList<>(Arrays.asList(TELEPHONY_TEST_CASES));
+ List<TelephonyTestCase> descendingCasesByScore = list(TELEPHONY_TEST_CASES);
Collections.reverse(descendingCasesByScore);
for (TelephonyTestCase testCase : descendingCasesByScore) {
@@ -504,7 +547,7 @@ public class TimeZoneDetectorStrategyImplTest {
Script script = new Script()
.initializeUser(USER_ID, UserCase.UNRESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED)
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED))
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
// Initialize the latest suggestions as empty so we don't need to worry about nulls
// below for the first loop.
@@ -583,15 +626,15 @@ public class TimeZoneDetectorStrategyImplTest {
}
/**
- * The {@link TimeZoneDetectorStrategyImpl.Callback} is left to detect whether changing
- * the time zone is actually necessary. This test proves that the service doesn't assume it
- * knows the current setting.
+ * The {@link TimeZoneDetectorStrategyImpl.Callback} is left to detect whether changing the time
+ * zone is actually necessary. This test proves that the strategy doesn't assume it knows the
+ * current settings.
*/
@Test
- public void testTelephonySuggestionTimeZoneDetectorStrategyDoesNotAssumeCurrentSetting() {
+ public void testTelephonySuggestionStrategyDoesNotAssumeCurrentSetting_autoTelephony() {
Script script = new Script()
.initializeUser(USER_ID, UserCase.UNRESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED);
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED));
TelephonyTestCase testCase = newTelephonyTestCase(
MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET, QUALITY_SINGLE_ZONE, TELEPHONY_SCORE_HIGH);
@@ -609,26 +652,40 @@ public class TimeZoneDetectorStrategyImplTest {
// Toggling time zone detection should set the device time zone only if the current setting
// value is different from the most recent telephony suggestion.
- script.simulateAutoTimeZoneDetectionEnabled(USER_ID, false)
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */)
.verifyTimeZoneNotChanged()
- .simulateAutoTimeZoneDetectionEnabled(USER_ID, true)
+ .simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */)
.verifyTimeZoneNotChanged();
// Simulate a user turning auto detection off, a new suggestion being made while auto
// detection is off, and the user turning it on again.
- script.simulateAutoTimeZoneDetectionEnabled(USER_ID, false)
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */)
.simulateTelephonyTimeZoneSuggestion(newYorkSuggestion)
.verifyTimeZoneNotChanged();
// Latest suggestion should be used.
- script.simulateAutoTimeZoneDetectionEnabled(USER_ID, true)
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */)
.verifyTimeZoneChangedAndReset(newYorkSuggestion);
}
@Test
- public void testManualSuggestion_unrestricted_simulateAutoTimeZoneEnabled() {
+ public void testManualSuggestion_autoDetectionEnabled_autoTelephony() {
+ checkManualSuggestion_autoDetectionEnabled(false /* geoDetectionEnabled */);
+ }
+
+ @Test
+ public void testManualSuggestion_autoDetectionEnabled_autoGeo() {
+ checkManualSuggestion_autoDetectionEnabled(true /* geoDetectionEnabled */);
+ }
+
+ private void checkManualSuggestion_autoDetectionEnabled(boolean geoDetectionEnabled) {
+ TimeZoneConfiguration geoTzEnabledConfig =
+ new TimeZoneConfiguration.Builder()
+ .setGeoDetectionEnabled(geoDetectionEnabled)
+ .build();
Script script = new Script()
.initializeUser(USER_ID, UserCase.UNRESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED)
+ CONFIG_AUTO_ENABLED.with(geoTzEnabledConfig))
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
// Auto time zone detection is enabled so the manual suggestion should be ignored.
@@ -641,7 +698,7 @@ public class TimeZoneDetectorStrategyImplTest {
public void testManualSuggestion_restricted_simulateAutoTimeZoneEnabled() {
Script script = new Script()
.initializeUser(USER_ID, UserCase.RESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED)
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED))
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
// Auto time zone detection is enabled so the manual suggestion should be ignored.
@@ -654,7 +711,7 @@ public class TimeZoneDetectorStrategyImplTest {
public void testManualSuggestion_autoDetectNotSupported_simulateAutoTimeZoneEnabled() {
Script script = new Script()
.initializeUser(USER_ID, UserCase.AUTO_DETECT_NOT_SUPPORTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_ENABLED)
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_DISABLED))
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
// Auto time zone detection is enabled so the manual suggestion should be ignored.
@@ -668,7 +725,7 @@ public class TimeZoneDetectorStrategyImplTest {
public void testManualSuggestion_unrestricted_autoTimeZoneDetectionDisabled() {
Script script = new Script()
.initializeUser(USER_ID, UserCase.UNRESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED)
+ CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED))
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
// Auto time zone detection is disabled so the manual suggestion should be used.
@@ -682,7 +739,7 @@ public class TimeZoneDetectorStrategyImplTest {
public void testManualSuggestion_restricted_autoTimeZoneDetectionDisabled() {
Script script = new Script()
.initializeUser(USER_ID, UserCase.RESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED)
+ CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED))
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
// Restricted users do not have the capability.
@@ -696,7 +753,7 @@ public class TimeZoneDetectorStrategyImplTest {
public void testManualSuggestion_autoDetectNotSupported_autoTimeZoneDetectionDisabled() {
Script script = new Script()
.initializeUser(USER_ID, UserCase.AUTO_DETECT_NOT_SUPPORTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED)
+ CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED))
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
// Unrestricted users have the capability.
@@ -707,10 +764,261 @@ public class TimeZoneDetectorStrategyImplTest {
}
@Test
+ public void testGeoSuggestion_uncertain() {
+ Script script = new Script()
+ .initializeUser(USER_ID, UserCase.UNRESTRICTED,
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_ENABLED))
+ .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+
+ GeolocationTimeZoneSuggestion uncertainSuggestion = createUncertainGeoLocationSuggestion();
+
+ script.simulateGeolocationTimeZoneSuggestion(uncertainSuggestion)
+ .verifyTimeZoneNotChanged();
+
+ // Assert internal service state.
+ assertEquals(uncertainSuggestion,
+ mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
+ }
+
+ @Test
+ public void testGeoSuggestion_noZones() {
+ Script script = new Script()
+ .initializeUser(USER_ID, UserCase.UNRESTRICTED,
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_ENABLED))
+ .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+
+ GeolocationTimeZoneSuggestion noZonesSuggestion = createGeoLocationSuggestion(list());
+
+ script.simulateGeolocationTimeZoneSuggestion(noZonesSuggestion)
+ .verifyTimeZoneNotChanged();
+
+ // Assert internal service state.
+ assertEquals(noZonesSuggestion, mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
+ }
+
+ @Test
+ public void testGeoSuggestion_oneZone() {
+ GeolocationTimeZoneSuggestion suggestion =
+ createGeoLocationSuggestion(list("Europe/London"));
+
+ Script script = new Script()
+ .initializeUser(USER_ID, UserCase.UNRESTRICTED,
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_ENABLED))
+ .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+
+ script.simulateGeolocationTimeZoneSuggestion(suggestion)
+ .verifyTimeZoneChangedAndReset("Europe/London");
+
+ // Assert internal service state.
+ assertEquals(suggestion, mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
+ }
+
+ /**
+ * In the current implementation, the first zone ID is always used unless the device is set to
+ * one of the other options. This is "stickiness" - the device favors the zone it is currently
+ * set to until that unambiguously can't be correct.
+ */
+ @Test
+ public void testGeoSuggestion_multiZone() {
+ GeolocationTimeZoneSuggestion londonOnlySuggestion =
+ createGeoLocationSuggestion(list("Europe/London"));
+ GeolocationTimeZoneSuggestion londonOrParisSuggestion =
+ createGeoLocationSuggestion(list("Europe/Paris", "Europe/London"));
+ GeolocationTimeZoneSuggestion parisOnlySuggestion =
+ createGeoLocationSuggestion(list("Europe/Paris"));
+
+ Script script = new Script()
+ .initializeUser(USER_ID, UserCase.UNRESTRICTED,
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_ENABLED))
+ .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+
+ script.simulateGeolocationTimeZoneSuggestion(londonOnlySuggestion)
+ .verifyTimeZoneChangedAndReset("Europe/London");
+ assertEquals(londonOnlySuggestion,
+ mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
+
+ // Confirm bias towards the current device zone when there's multiple zones to choose from.
+ script.simulateGeolocationTimeZoneSuggestion(londonOrParisSuggestion)
+ .verifyTimeZoneNotChanged();
+ assertEquals(londonOrParisSuggestion,
+ mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
+
+ script.simulateGeolocationTimeZoneSuggestion(parisOnlySuggestion)
+ .verifyTimeZoneChangedAndReset("Europe/Paris");
+ assertEquals(parisOnlySuggestion,
+ mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
+
+ // Now the suggestion that previously left the device on Europe/London will leave the device
+ // on Europe/Paris.
+ script.simulateGeolocationTimeZoneSuggestion(londonOrParisSuggestion)
+ .verifyTimeZoneNotChanged();
+ assertEquals(londonOrParisSuggestion,
+ mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
+ }
+
+ /**
+ * Confirms that toggling the auto time zone detection enabled setting has the expected behavior
+ * when the strategy is "opinionated" and "un-opinionated" when in geolocation detection is
+ * enabled.
+ */
+ @Test
+ public void testTogglingAutoDetectionEnabled_autoGeo() {
+ GeolocationTimeZoneSuggestion geolocationSuggestion =
+ createGeoLocationSuggestion(list("Europe/London"));
+ GeolocationTimeZoneSuggestion uncertainGeolocationSuggestion =
+ createUncertainGeoLocationSuggestion();
+ ManualTimeZoneSuggestion manualSuggestion = createManualSuggestion("Europe/Paris");
+
+ Script script = new Script()
+ .initializeUser(USER_ID, UserCase.UNRESTRICTED,
+ CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_ENABLED))
+ .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+
+ script.simulateGeolocationTimeZoneSuggestion(geolocationSuggestion);
+
+ // When time zone detection is not enabled, the time zone suggestion will not be set.
+ script.verifyTimeZoneNotChanged();
+
+ // Assert internal service state.
+ assertEquals(geolocationSuggestion,
+ mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
+
+ // Toggling the time zone setting on should cause the device setting to be set.
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */)
+ .verifyTimeZoneChangedAndReset("Europe/London");
+
+ // Toggling the time zone setting should off should do nothing because the device is now
+ // set to that time zone.
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */)
+ .verifyTimeZoneNotChanged()
+ .simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */)
+ .verifyTimeZoneNotChanged();
+
+ // Now toggle auto time zone setting, and confirm it is opinionated.
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */)
+ .simulateManualTimeZoneSuggestion(
+ USER_ID, manualSuggestion, true /* expectedResult */)
+ .verifyTimeZoneChangedAndReset(manualSuggestion)
+ .simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */)
+ .verifyTimeZoneChangedAndReset("Europe/London");
+
+ // Now withdraw the geolocation suggestion, and assert the strategy is no longer
+ // opinionated.
+ /* expectedResult */
+ script.simulateGeolocationTimeZoneSuggestion(uncertainGeolocationSuggestion)
+ .verifyTimeZoneNotChanged()
+ .simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */)
+ .verifyTimeZoneNotChanged()
+ .simulateManualTimeZoneSuggestion(
+ USER_ID, manualSuggestion, true /* expectedResult */)
+ .verifyTimeZoneChangedAndReset(manualSuggestion)
+ .simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */)
+ .verifyTimeZoneNotChanged();
+
+ // Assert internal service state.
+ assertEquals(uncertainGeolocationSuggestion,
+ mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
+ }
+
+ /**
+ * Confirms that changing the geolocation time zone detection enabled setting has the expected
+ * behavior, i.e. immediately recompute the detected time zone using different signals.
+ */
+ @Test
+ public void testChangingGeoDetectionEnabled() {
+ GeolocationTimeZoneSuggestion geolocationSuggestion =
+ createGeoLocationSuggestion(list("Europe/London"));
+ TelephonyTimeZoneSuggestion telephonySuggestion = createTelephonySuggestion(
+ SLOT_INDEX1, MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET, QUALITY_SINGLE_ZONE,
+ "Europe/Paris");
+
+ Script script = new Script()
+ .initializeUser(USER_ID, UserCase.UNRESTRICTED,
+ CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED))
+ .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+
+ // Add suggestions. Nothing should happen as time zone detection is disabled.
+ script.simulateGeolocationTimeZoneSuggestion(geolocationSuggestion)
+ .verifyTimeZoneNotChanged();
+ script.simulateTelephonyTimeZoneSuggestion(telephonySuggestion)
+ .verifyTimeZoneNotChanged();
+
+ // Assert internal service state.
+ assertEquals(geolocationSuggestion,
+ mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
+ assertEquals(telephonySuggestion,
+ mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1).suggestion);
+
+ // Toggling the time zone detection enabled setting on should cause the device setting to be
+ // set from the telephony signal, as we've started with geolocation time zone detection
+ // disabled.
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */)
+ .verifyTimeZoneChangedAndReset(telephonySuggestion);
+
+ // Changing the detection to enable geo detection should cause the device tz setting to
+ // change to the geo suggestion.
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_GEO_DETECTION_ENABLED, true /* expectedResult */)
+ .verifyTimeZoneChangedAndReset(geolocationSuggestion.getZoneIds().get(0));
+
+ // Changing the detection to disable geo detection should cause the device tz setting to
+ // change to the telephony suggestion.
+ script.simulateUpdateConfiguration(
+ USER_ID, CONFIG_GEO_DETECTION_DISABLED, true /* expectedResult */)
+ .verifyTimeZoneChangedAndReset(telephonySuggestion);
+ }
+
+ /**
+ * The {@link TimeZoneDetectorStrategyImpl.Callback} is left to detect whether changing the time
+ * zone is actually necessary. This test proves that the strategy doesn't assume it knows the
+ * current setting.
+ */
+ @Test
+ public void testTimeZoneDetectorStrategyDoesNotAssumeCurrentSetting_autoGeo() {
+ GeolocationTimeZoneSuggestion losAngelesSuggestion =
+ createGeoLocationSuggestion(list("America/Los_Angeles"));
+ GeolocationTimeZoneSuggestion newYorkSuggestion =
+ createGeoLocationSuggestion(list("America/New_York"));
+
+ Script script = new Script()
+ .initializeUser(USER_ID, UserCase.UNRESTRICTED,
+ CONFIG_AUTO_ENABLED.with(CONFIG_GEO_DETECTION_ENABLED));
+
+ // Initialization.
+ script.simulateGeolocationTimeZoneSuggestion(losAngelesSuggestion)
+ .verifyTimeZoneChangedAndReset("America/Los_Angeles");
+ // Suggest it again - it should not be set because it is already set.
+ script.simulateGeolocationTimeZoneSuggestion(losAngelesSuggestion)
+ .verifyTimeZoneNotChanged();
+
+ // Toggling time zone detection should set the device time zone only if the current setting
+ // value is different from the most recent telephony suggestion.
+ /* expectedResult */
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */)
+ .verifyTimeZoneNotChanged()
+ .simulateUpdateConfiguration(
+ USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */)
+ .verifyTimeZoneNotChanged();
+
+ // Simulate a user turning auto detection off, a new suggestion being made while auto
+ // detection is off, and the user turning it on again.
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */)
+ .simulateGeolocationTimeZoneSuggestion(newYorkSuggestion)
+ .verifyTimeZoneNotChanged();
+ // Latest suggestion should be used.
+ script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */)
+ .verifyTimeZoneChangedAndReset("America/New_York");
+ }
+
+ @Test
public void testAddDumpable() {
new Script()
.initializeUser(USER_ID, UserCase.UNRESTRICTED,
- CONFIG_AUTO_TIME_ZONE_DETECTION_DISABLED)
+ CONFIG_AUTO_DISABLED.with(CONFIG_GEO_DETECTION_DISABLED))
.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
AtomicBoolean dumpCalled = new AtomicBoolean(false);
@@ -733,6 +1041,15 @@ public class TimeZoneDetectorStrategyImplTest {
return new ManualTimeZoneSuggestion(zoneId);
}
+ private static TelephonyTimeZoneSuggestion createTelephonySuggestion(
+ int slotIndex, @MatchType int matchType, @Quality int quality, String zoneId) {
+ return new TelephonyTimeZoneSuggestion.Builder(slotIndex)
+ .setMatchType(matchType)
+ .setQuality(quality)
+ .setZoneId(zoneId)
+ .build();
+ }
+
private static TelephonyTimeZoneSuggestion createEmptySlotIndex1Suggestion() {
return new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX1).build();
}
@@ -741,6 +1058,17 @@ public class TimeZoneDetectorStrategyImplTest {
return new TelephonyTimeZoneSuggestion.Builder(SLOT_INDEX2).build();
}
+ private static GeolocationTimeZoneSuggestion createUncertainGeoLocationSuggestion() {
+ return createGeoLocationSuggestion(null);
+ }
+
+ private static GeolocationTimeZoneSuggestion createGeoLocationSuggestion(
+ @Nullable List<String> zoneIds) {
+ GeolocationTimeZoneSuggestion suggestion = new GeolocationTimeZoneSuggestion(zoneIds);
+ suggestion.addDebugInfo("Test suggestion");
+ return suggestion;
+ }
+
static class FakeCallback implements TimeZoneDetectorStrategyImpl.Callback {
private TimeZoneCapabilities mCapabilities;
@@ -757,7 +1085,8 @@ public class TimeZoneDetectorStrategyImplTest {
TimeZoneConfiguration configuration) {
assertEquals(userId, capabilities.getUserId());
mCapabilities = capabilities;
- assertTrue(configuration.isComplete());
+ assertTrue("Configuration must be complete when initializing, config=" + configuration,
+ configuration.isComplete());
mConfiguration.init(new UserConfiguration(userId, configuration));
}
@@ -790,11 +1119,8 @@ public class TimeZoneDetectorStrategyImplTest {
mConfiguration.set(new UserConfiguration(userId, newConfig));
if (!newConfig.equals(oldConfig)) {
- if (oldConfig.isAutoDetectionEnabled() != newConfig.isAutoDetectionEnabled()) {
- // Simulate what happens when the auto detection enabled configuration is
- // changed.
- mStrategy.handleAutoTimeZoneConfigChanged();
- }
+ // Simulate what happens when the auto detection configuration is changed.
+ mStrategy.handleAutoTimeZoneConfigChanged();
}
}
@@ -804,6 +1130,11 @@ public class TimeZoneDetectorStrategyImplTest {
}
@Override
+ public boolean isGeoDetectionEnabled() {
+ return mConfiguration.getLatest().configuration.isGeoDetectionEnabled();
+ }
+
+ @Override
public boolean isDeviceTimeZoneInitialized() {
return mTimeZoneId.getLatest() != null;
}
@@ -942,32 +1273,33 @@ public class TimeZoneDetectorStrategyImplTest {
* supplied configuration.
*/
private static TimeZoneCapabilities createCapabilities(
- int userId, UserCase userRole, TimeZoneConfiguration configuration) {
- switch (userRole) {
+ int userId, UserCase userCase, TimeZoneConfiguration configuration) {
+ switch (userCase) {
case UNRESTRICTED: {
int suggestManualTimeZoneCapability = configuration.isAutoDetectionEnabled()
? CAPABILITY_NOT_APPLICABLE : CAPABILITY_POSSESSED;
return new TimeZoneCapabilities.Builder(userId)
.setConfigureAutoDetectionEnabled(CAPABILITY_POSSESSED)
+ .setConfigureGeoDetectionEnabled(CAPABILITY_POSSESSED)
.setSuggestManualTimeZone(suggestManualTimeZoneCapability)
.build();
}
case RESTRICTED: {
return new TimeZoneCapabilities.Builder(userId)
.setConfigureAutoDetectionEnabled(CAPABILITY_NOT_ALLOWED)
+ .setConfigureGeoDetectionEnabled(CAPABILITY_NOT_ALLOWED)
.setSuggestManualTimeZone(CAPABILITY_NOT_ALLOWED)
.build();
-
}
case AUTO_DETECT_NOT_SUPPORTED: {
return new TimeZoneCapabilities.Builder(userId)
.setConfigureAutoDetectionEnabled(CAPABILITY_NOT_SUPPORTED)
+ .setConfigureGeoDetectionEnabled(CAPABILITY_NOT_SUPPORTED)
.setSuggestManualTimeZone(CAPABILITY_POSSESSED)
.build();
-
}
default:
- throw new AssertionError(userRole + " not recognized");
+ throw new AssertionError(userCase + " not recognized");
}
}
@@ -978,8 +1310,8 @@ public class TimeZoneDetectorStrategyImplTest {
private class Script {
Script initializeUser(
- @UserIdInt int userId, UserCase userRole, TimeZoneConfiguration configuration) {
- TimeZoneCapabilities capabilities = createCapabilities(userId, userRole, configuration);
+ @UserIdInt int userId, UserCase userCase, TimeZoneConfiguration configuration) {
+ TimeZoneCapabilities capabilities = createCapabilities(userId, userCase, configuration);
mFakeCallback.initializeUser(userId, capabilities, configuration);
return this;
}
@@ -989,27 +1321,24 @@ public class TimeZoneDetectorStrategyImplTest {
return this;
}
- Script simulateAutoTimeZoneDetectionEnabled(@UserIdInt int userId, boolean enabled) {
- TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
- .setAutoDetectionEnabled(enabled)
- .build();
- return simulateUpdateConfiguration(userId, configuration);
- }
-
/**
- * Simulates the time zone detection strategy receiving an updated configuration.
+ * Simulates the time zone detection strategy receiving an updated configuration and checks
+ * the return value.
*/
Script simulateUpdateConfiguration(
- @UserIdInt int userId, TimeZoneConfiguration configuration) {
- mTimeZoneDetectorStrategy.updateConfiguration(userId, configuration);
+ @UserIdInt int userId, TimeZoneConfiguration configuration,
+ boolean expectedResult) {
+ assertEquals(expectedResult,
+ mTimeZoneDetectorStrategy.updateConfiguration(userId, configuration));
return this;
}
/**
- * Simulates the time zone detection strategy receiving a telephony-originated suggestion.
+ * Simulates the time zone detection strategy receiving a geolocation-originated
+ * suggestion.
*/
- Script simulateTelephonyTimeZoneSuggestion(TelephonyTimeZoneSuggestion timeZoneSuggestion) {
- mTimeZoneDetectorStrategy.suggestTelephonyTimeZone(timeZoneSuggestion);
+ Script simulateGeolocationTimeZoneSuggestion(GeolocationTimeZoneSuggestion suggestion) {
+ mTimeZoneDetectorStrategy.suggestGeolocationTimeZone(suggestion);
return this;
}
@@ -1024,13 +1353,26 @@ public class TimeZoneDetectorStrategyImplTest {
return this;
}
+ /**
+ * Simulates the time zone detection strategy receiving a telephony-originated suggestion.
+ */
+ Script simulateTelephonyTimeZoneSuggestion(TelephonyTimeZoneSuggestion timeZoneSuggestion) {
+ mTimeZoneDetectorStrategy.suggestTelephonyTimeZone(timeZoneSuggestion);
+ return this;
+ }
+
+ /**
+ * Confirms that the device's time zone has not been set by previous actions since the test
+ * state was last reset.
+ */
Script verifyTimeZoneNotChanged() {
mFakeCallback.assertTimeZoneNotChanged();
return this;
}
- Script verifyTimeZoneChangedAndReset(TelephonyTimeZoneSuggestion suggestion) {
- mFakeCallback.assertTimeZoneChangedTo(suggestion.getZoneId());
+ /** Verifies the device's time zone has been set and clears change tracking history. */
+ Script verifyTimeZoneChangedAndReset(String zoneId) {
+ mFakeCallback.assertTimeZoneChangedTo(zoneId);
mFakeCallback.commitAllChanges();
return this;
}
@@ -1041,6 +1383,12 @@ public class TimeZoneDetectorStrategyImplTest {
return this;
}
+ Script verifyTimeZoneChangedAndReset(TelephonyTimeZoneSuggestion suggestion) {
+ mFakeCallback.assertTimeZoneChangedTo(suggestion.getZoneId());
+ mFakeCallback.commitAllChanges();
+ return this;
+ }
+
/**
* Verifies that the configuration has been changed to the expected value.
*/
@@ -1120,4 +1468,8 @@ public class TimeZoneDetectorStrategyImplTest {
mOnConfigurationChangedCalled = false;
}
}
+
+ private static <T> List<T> list(T... values) {
+ return Arrays.asList(values);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 4dec7a1a0ab9..7c7b1a296673 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -1383,7 +1383,7 @@ public class AppStandbyControllerTests {
getStandbyBucket(mController, PACKAGE_1));
mController.postReportSyncScheduled(PACKAGE_1, USER_ID, false);
- mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
+ mStateChangedLatch.await(1000, TimeUnit.MILLISECONDS);
assertEquals("Unexempted sync scheduled should bring the package out of the Never bucket",
STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
@@ -1391,7 +1391,7 @@ public class AppStandbyControllerTests {
mStateChangedLatch = new CountDownLatch(1);
mController.postReportSyncScheduled(PACKAGE_1, USER_ID, false);
- mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
+ mStateChangedLatch.await(1000, TimeUnit.MILLISECONDS);
assertEquals("Unexempted sync scheduled should not elevate a non Never bucket",
STANDBY_BUCKET_RARE, getStandbyBucket(mController, PACKAGE_1));
}
@@ -1402,7 +1402,7 @@ public class AppStandbyControllerTests {
mInjector.mDeviceIdleMode = true;
mStateChangedLatch = new CountDownLatch(1);
mController.postReportSyncScheduled(PACKAGE_1, USER_ID, true);
- mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
+ mStateChangedLatch.await(1000, TimeUnit.MILLISECONDS);
assertEquals("Exempted sync scheduled in doze should set bucket to working set",
STANDBY_BUCKET_WORKING_SET, getStandbyBucket(mController, PACKAGE_1));
@@ -1410,7 +1410,7 @@ public class AppStandbyControllerTests {
mInjector.mDeviceIdleMode = false;
mStateChangedLatch = new CountDownLatch(1);
mController.postReportSyncScheduled(PACKAGE_1, USER_ID, true);
- mStateChangedLatch.await(100, TimeUnit.MILLISECONDS);
+ mStateChangedLatch.await(1000, TimeUnit.MILLISECONDS);
assertEquals("Exempted sync scheduled while not in doze should set bucket to active",
STANDBY_BUCKET_ACTIVE, getStandbyBucket(mController, PACKAGE_1));
}
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java
deleted file mode 100644
index f6c854e23494..000000000000
--- a/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.server.slice;
-
-import static org.junit.Assert.assertTrue;
-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.testing.AndroidTestingRunner;
-import android.testing.TestableLooper.RunWithLooper;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.server.UiServiceTestCase;
-import com.android.server.slice.SliceManagerService.PackageMatchingCache;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.function.Supplier;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper
-public class PackageMatchingCacheTest extends UiServiceTestCase {
-
- private final Supplier<String> supplier = mock(Supplier.class);
- private final PackageMatchingCache cache = new PackageMatchingCache(supplier);
-
- @Test
- public void testNulls() {
- // Doesn't get for a null input
- cache.matches(null);
- verify(supplier, never()).get();
-
- // Gets once valid input in sent.
- cache.matches("");
- verify(supplier).get();
- }
-
- @Test
- public void testCaching() {
- when(supplier.get()).thenReturn("ret.pkg");
-
- assertTrue(cache.matches("ret.pkg"));
- assertTrue(cache.matches("ret.pkg"));
- assertTrue(cache.matches("ret.pkg"));
-
- verify(supplier, times(1)).get();
- }
-
- @Test
- public void testGetOnFailure() {
- when(supplier.get()).thenReturn("ret.pkg");
- assertTrue(cache.matches("ret.pkg"));
-
- when(supplier.get()).thenReturn("other.pkg");
- assertTrue(cache.matches("other.pkg"));
- verify(supplier, times(2)).get();
- }
-}
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
index a4436951f48b..cf1c36c0d243 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java
@@ -90,8 +90,6 @@ public class SliceManagerServiceTest extends UiServiceTestCase {
@Test
public void testAddPinCreatesPinned() throws RemoteException {
- doReturn("pkg").when(mService).getDefaultHome(anyInt());
-
mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
verify(mService, times(1)).createPinnedSlice(eq(maybeAddUserId(TEST_URI, 0)), anyString());
@@ -99,8 +97,6 @@ public class SliceManagerServiceTest extends UiServiceTestCase {
@Test
public void testRemovePinDestroysPinned() throws RemoteException {
- doReturn("pkg").when(mService).getDefaultHome(anyInt());
-
mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken);
when(mCreatedSliceState.unpin(eq("pkg"), eq(mToken))).thenReturn(false);
diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp
index b3d75d31cb60..4ca5b9e4b14f 100644
--- a/services/tests/wmtests/Android.bp
+++ b/services/tests/wmtests/Android.bp
@@ -2,15 +2,37 @@
// Build WmTests package
//########################################################################
+// Include all test java files.
+filegroup {
+ name: "wmtests-sources",
+ srcs: [
+ "src/**/*.java",
+ ],
+}
+
+genrule {
+ name: "wmtests.protologsrc",
+ srcs: [
+ ":protolog-groups",
+ ":wmtests-sources",
+ ],
+ tools: ["protologtool"],
+ cmd: "$(location protologtool) transform-protolog-calls " +
+ "--protolog-class com.android.internal.protolog.common.ProtoLog " +
+ "--protolog-impl-class com.android.internal.protolog.ProtoLogImpl " +
+ "--protolog-cache-class 'com.android.server.wm.ProtoLogCache' " +
+ "--loggroups-class com.android.internal.protolog.ProtoLogGroup " +
+ "--loggroups-jar $(location :protolog-groups) " +
+ "--output-srcjar $(out) " +
+ "$(locations :wmtests-sources)",
+ out: ["wmtests.protolog.srcjar"],
+}
+
android_test {
name: "WmTests",
// We only want this apk build for tests.
-
- // Include all test java files.
- srcs: [
- "src/**/*.java",
- ],
+ srcs: [":wmtests.protologsrc"],
static_libs: [
"frameworks-base-testutils",
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 6061f13fcee5..f860e174fd15 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1506,7 +1506,7 @@ public class ActivityRecordTests extends WindowTestsBase {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
params.width = params.height = WindowManager.LayoutParams.MATCH_PARENT;
- final WindowTestUtils.TestWindowState w = new WindowTestUtils.TestWindowState(
+ final TestWindowState w = new TestWindowState(
mAtm.mWindowManager, mock(Session.class), new TestIWindow(), params, mActivity);
mActivity.addWindow(w);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 2e988af29638..567610018fc1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -225,5 +225,27 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
mockSession.finishMocking();
}
+
+ @Test
+ public void testResumeNextActivityOnCrashedAppDied() {
+ mSupervisor.beginDeferResume();
+ final ActivityRecord homeActivity = new ActivityBuilder(mAtm)
+ .setTask(mRootWindowContainer.getDefaultTaskDisplayArea().getOrCreateRootHomeTask())
+ .build();
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ mSupervisor.endDeferResume();
+ // Assume the activity is finishing and hidden because it was crashed.
+ activity.finishing = true;
+ activity.mVisibleRequested = false;
+ activity.setVisible(false);
+ activity.getRootTask().mPausingActivity = activity;
+ homeActivity.setState(Task.ActivityState.PAUSED, "test");
+
+ // Even the visibility states are invisible, the next activity should be resumed because
+ // the crashed activity was pausing.
+ mAtm.mInternal.handleAppDied(activity.app, false /* restarting */,
+ null /* finishInstrumentationCallback */);
+ assertEquals(Task.ActivityState.RESUMED, homeActivity.getState());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 7adceade0b9b..1b2192035213 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -133,10 +133,10 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// [DisplayContent] -+- [TaskStack1] - [Task1] - [ActivityRecord1] (opening, visible)
// +- [TaskStack2] - [Task2] - [ActivityRecord2] (closing, invisible)
final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(stack1);
+ final ActivityRecord activity1 = createTestActivityRecord(stack1);
final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(stack2);
+ final ActivityRecord activity2 = createTestActivityRecord(stack2);
activity2.setVisible(false);
activity2.mVisibleRequested = false;
@@ -162,13 +162,13 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// [DisplayContent] -+- [TaskStack1] - [Task1] - [ActivityRecord1] (closing, invisible)
// +- [TaskStack2] - [Task2] - [ActivityRecord2] (opening, visible)
final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(stack1);
+ final ActivityRecord activity1 = createTestActivityRecord(stack1);
activity1.setVisible(true);
activity1.mVisibleRequested = true;
activity1.mRequestForceTransition = true;
final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(stack2);
+ final ActivityRecord activity2 = createTestActivityRecord(stack2);
activity2.setVisible(false);
activity2.mVisibleRequested = false;
activity2.mRequestForceTransition = true;
@@ -193,10 +193,10 @@ public class AppTransitionControllerTest extends WindowTestsBase {
@Test
public void testGetAnimationTargets_exitingBeforeTransition() {
// Create another non-empty task so the animation target won't promote to task display area.
- WindowTestUtils.createTestActivityRecord(
+ createTestActivityRecord(
mDisplayContent.getDefaultTaskDisplayArea().getOrCreateRootHomeTask());
final Task stack = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(stack);
+ final ActivityRecord activity = createTestActivityRecord(stack);
activity.setVisible(false);
activity.mIsExiting = true;
@@ -218,20 +218,20 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// +- [TaskStack2] - [Task2] - [ActivityRecord2] (closing, invisible)
// +- [AppWindow2] (being-replaced)
final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(stack1);
+ final ActivityRecord activity1 = createTestActivityRecord(stack1);
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
TYPE_BASE_APPLICATION);
attrs.setTitle("AppWindow1");
- final WindowTestUtils.TestWindowState appWindow1 = createWindowState(attrs, activity1);
+ final TestWindowState appWindow1 = createWindowState(attrs, activity1);
appWindow1.mWillReplaceWindow = true;
activity1.addWindow(appWindow1);
final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(stack2);
+ final ActivityRecord activity2 = createTestActivityRecord(stack2);
activity2.setVisible(false);
activity2.mVisibleRequested = false;
attrs.setTitle("AppWindow2");
- final WindowTestUtils.TestWindowState appWindow2 = createWindowState(attrs, activity2);
+ final TestWindowState appWindow2 = createWindowState(attrs, activity2);
appWindow2.mWillReplaceWindow = true;
activity2.addWindow(appWindow2);
@@ -262,21 +262,17 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// +- [ActivityRecord4] (invisible)
final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack1, 0 /* userId */);
- final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task1);
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task1);
activity1.setVisible(false);
activity1.mVisibleRequested = true;
- final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task1);
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task1);
activity2.setVisible(false);
activity2.mVisibleRequested = false;
final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
final Task task2 = createTaskInStack(stack2, 0 /* userId */);
- final ActivityRecord activity3 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task2);
- final ActivityRecord activity4 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task2);
+ final ActivityRecord activity3 = createActivityRecordInTask(mDisplayContent, task2);
+ final ActivityRecord activity4 = createActivityRecordInTask(mDisplayContent, task2);
activity4.setVisible(false);
activity4.mVisibleRequested = false;
@@ -303,12 +299,10 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// +- [ActivityRecord2] (closing, visible)
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task);
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task);
activity1.setVisible(false);
activity1.mVisibleRequested = true;
- final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task);
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -337,22 +331,18 @@ public class AppTransitionControllerTest extends WindowTestsBase {
final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack1, 0 /* userId */);
- final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task1);
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task1);
activity1.setVisible(false);
activity1.mVisibleRequested = true;
activity1.setOccludesParent(false);
- final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task1);
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task1);
final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
final Task task2 = createTaskInStack(stack2, 0 /* userId */);
- final ActivityRecord activity3 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task2);
+ final ActivityRecord activity3 = createActivityRecordInTask(mDisplayContent, task2);
activity3.setOccludesParent(false);
- final ActivityRecord activity4 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task2);
+ final ActivityRecord activity4 = createActivityRecordInTask(mDisplayContent, task2);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -381,24 +371,20 @@ public class AppTransitionControllerTest extends WindowTestsBase {
final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack1, 0 /* userId */);
- final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task1);
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task1);
activity1.setVisible(false);
activity1.mVisibleRequested = true;
activity1.setOccludesParent(false);
- final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task1);
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task1);
activity2.setVisible(false);
activity2.mVisibleRequested = true;
final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
final Task task2 = createTaskInStack(stack2, 0 /* userId */);
- final ActivityRecord activity3 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task2);
+ final ActivityRecord activity3 = createActivityRecordInTask(mDisplayContent, task2);
activity3.setOccludesParent(false);
- final ActivityRecord activity4 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task2);
+ final ActivityRecord activity4 = createActivityRecordInTask(mDisplayContent, task2);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -425,13 +411,11 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// +- [Task2] - [ActivityRecord2] (closing, visible)
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task1);
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task1);
activity1.setVisible(false);
activity1.mVisibleRequested = true;
final Task task2 = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(
- mDisplayContent, task2);
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task2);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 17914e7fb68c..ee030af36b8f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -151,8 +151,7 @@ public class AppTransitionTests extends WindowTestsBase {
final Task stack1 = createTaskStackOnDisplay(dc1);
final Task task1 = createTaskInStack(stack1, 0 /* userId */);
- final ActivityRecord activity1 =
- WindowTestUtils.createTestActivityRecord(dc1);
+ final ActivityRecord activity1 = createTestActivityRecord(dc1);
task1.addChild(activity1, 0);
// Simulate same app is during opening / closing transition set stage.
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 888935ef9747..085b8dec2cb7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -92,7 +92,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
public void setUp() throws Exception {
mStack = createTaskStackOnDisplay(mDisplayContent);
mTask = createTaskInStack(mStack, 0 /* userId */);
- mActivity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ mActivity = createTestActivityRecord(mDisplayContent);
mTask.addChild(mActivity, 0);
}
@@ -165,7 +165,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
TYPE_BASE_APPLICATION);
attrs.setTitle("AppWindow");
- final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mActivity);
+ final TestWindowState appWindow = createWindowState(attrs, mActivity);
mActivity.addWindow(appWindow);
// Set initial orientation and update.
@@ -198,7 +198,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
TYPE_BASE_APPLICATION);
attrs.setTitle("RotationByPolicy");
- final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mActivity);
+ final TestWindowState appWindow = createWindowState(attrs, mActivity);
mActivity.addWindow(appWindow);
// Set initial orientation and update.
@@ -244,7 +244,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
TYPE_BASE_APPLICATION);
attrs.flags |= FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD;
attrs.setTitle("AppWindow");
- final WindowTestUtils.TestWindowState appWindow = createWindowState(attrs, mActivity);
+ final TestWindowState appWindow = createWindowState(attrs, mActivity);
// Add window with show when locked flag
mActivity.addWindow(appWindow);
@@ -307,7 +307,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
assertEquals(Configuration.ORIENTATION_PORTRAIT, displayConfig.orientation);
assertEquals(Configuration.ORIENTATION_PORTRAIT, activityConfig.orientation);
- final ActivityRecord topActivity = WindowTestUtils.createTestActivityRecord(mStack);
+ final ActivityRecord topActivity = createTestActivityRecord(mStack);
topActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
assertEquals(Configuration.ORIENTATION_LANDSCAPE, displayConfig.orientation);
@@ -490,8 +490,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
}
private ActivityRecord createTestActivityRecordForGivenTask(Task task) {
- final ActivityRecord activity =
- WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
task.addChild(activity, 0);
waitUntilHandlersIdle();
return activity;
@@ -562,7 +561,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
public void testHasStartingWindow() {
final WindowManager.LayoutParams attrs =
new WindowManager.LayoutParams(TYPE_APPLICATION_STARTING);
- final WindowTestUtils.TestWindowState startingWindow = createWindowState(attrs, mActivity);
+ final TestWindowState startingWindow = createWindowState(attrs, mActivity);
mActivity.startingDisplayed = true;
mActivity.addWindow(startingWindow);
assertTrue("Starting window should be present", mActivity.hasStartingWindow());
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 0cc61599c2ac..d54b4a0a72f6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -326,7 +326,7 @@ public class DisplayContentTests extends WindowTestsBase {
assertEquals(dc, stack.getDisplayContent());
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(dc);
+ final ActivityRecord activity = createTestActivityRecord(dc);
task.addChild(activity, 0);
assertEquals(dc, task.getDisplayContent());
assertEquals(dc, activity.getDisplayContent());
@@ -397,16 +397,14 @@ public class DisplayContentTests extends WindowTestsBase {
// Add stack with activity.
final Task stack0 = createTaskStackOnDisplay(dc0);
final Task task0 = createTaskInStack(stack0, 0 /* userId */);
- final ActivityRecord activity =
- WindowTestUtils.createTestActivityRecord(dc0);
+ final ActivityRecord activity = createTestActivityRecord(dc0);
task0.addChild(activity, 0);
dc0.configureDisplayPolicy();
assertNotNull(dc0.mTapDetector);
final Task stack1 = createTaskStackOnDisplay(dc1);
final Task task1 = createTaskInStack(stack1, 0 /* userId */);
- final ActivityRecord activity1 =
- WindowTestUtils.createTestActivityRecord(dc0);
+ final ActivityRecord activity1 = createTestActivityRecord(dc0);
task1.addChild(activity1, 0);
dc1.configureDisplayPolicy();
assertNotNull(dc1.mTapDetector);
@@ -1296,7 +1294,7 @@ public class DisplayContentTests extends WindowTestsBase {
final ActivityRecord pinnedActivity = createActivityRecord(displayContent,
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
final Task pinnedTask = pinnedActivity.getRootTask();
- final ActivityRecord homeActivity = WindowTestUtils.createTestActivityRecord(
+ final ActivityRecord homeActivity = createTestActivityRecord(
displayContent.getDefaultTaskDisplayArea().getOrCreateRootHomeTask());
if (displayConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
homeActivity.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 4ea5b97decf4..0675c6d04422 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -48,12 +48,14 @@ import static android.view.WindowManagerPolicyConstants.ALT_BAR_LEFT;
import static android.view.WindowManagerPolicyConstants.ALT_BAR_RIGHT;
import static android.view.WindowManagerPolicyConstants.ALT_BAR_TOP;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
@@ -874,6 +876,19 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
}
@Test
+ public void testFixedRotationInsetsSourceFrame() {
+ mDisplayPolicy.beginLayoutLw(mFrames, mDisplayContent.getConfiguration().uiMode);
+ doReturn((mDisplayContent.getRotation() + 1) % 4).when(mDisplayContent)
+ .rotationForActivityInDifferentOrientation(eq(mWindow.mActivityRecord));
+ final Rect frame = mWindow.getInsetsState().getSource(ITYPE_STATUS_BAR).getFrame();
+ mDisplayContent.rotateInDifferentOrientationIfNeeded(mWindow.mActivityRecord);
+ final Rect rotatedFrame = mWindow.getInsetsState().getSource(ITYPE_STATUS_BAR).getFrame();
+
+ assertEquals(DISPLAY_WIDTH, frame.width());
+ assertEquals(DISPLAY_HEIGHT, rotatedFrame.width());
+ }
+
+ @Test
public void testScreenDecorWindows() {
final WindowState decorWindow = spy(
createWindow(null, TYPE_APPLICATION_OVERLAY, "decorWindow"));
diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index e18d93d82686..45369975fcc5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -95,8 +95,7 @@ public class DragDropControllerTests extends WindowTestsBase {
* Creates a window state which can be used as a drop target.
*/
private WindowState createDropTargetWindow(String name, int ownerId) {
- final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(
- mDisplayContent);
+ final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
final Task stack = createTaskStackOnDisplay(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent);
final Task task = createTaskInStack(stack, ownerId);
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index 5e83e66536ed..085230d35c6a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -28,6 +28,9 @@ import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -40,6 +43,7 @@ import static org.mockito.Mockito.verify;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
+import android.util.IntArray;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.test.InsetsModeSession;
@@ -328,6 +332,27 @@ public class InsetsStateControllerTest extends WindowTestsBase {
assertNull(getController().getControlsForDispatch(app));
}
+ @Test
+ public void testTransientVisibilityOfFixedRotationState() {
+ final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ final InsetsSourceProvider provider = getController().getSourceProvider(ITYPE_STATUS_BAR);
+ provider.setWindow(statusBar, null, null);
+
+ final InsetsState rotatedState = new InsetsState(app.getInsetsState(),
+ true /* copySources */);
+ spyOn(app.mToken);
+ doReturn(rotatedState).when(app.mToken).getFixedRotationTransformInsetsState();
+ assertTrue(rotatedState.getSource(ITYPE_STATUS_BAR).isVisible());
+
+ provider.getSource().setVisible(false);
+ mDisplayContent.getInsetsPolicy().showTransient(
+ IntArray.wrap(new int[] { ITYPE_STATUS_BAR }));
+
+ assertTrue(mDisplayContent.getInsetsPolicy().isTransient(ITYPE_STATUS_BAR));
+ assertFalse(app.getInsetsState().getSource(ITYPE_STATUS_BAR).isVisible());
+ }
+
private InsetsStateController getController() {
return mDisplayContent.getInsetsStateController();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java b/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java
index d1510cf811fb..8223024234fb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ProtoLogIntegrationTest.java
@@ -25,9 +25,12 @@ import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
-import com.android.server.protolog.ProtoLogImpl;
+import com.android.internal.protolog.ProtoLogGroup;
+import com.android.internal.protolog.ProtoLogImpl;
+import com.android.internal.protolog.common.ProtoLog;
import org.junit.After;
+import org.junit.Ignore;
import org.junit.Test;
/**
@@ -35,6 +38,7 @@ import org.junit.Test;
*/
@SmallTest
@Presubmit
+@Ignore("b/163095037")
public class ProtoLogIntegrationTest {
@After
public void tearDown() {
@@ -44,17 +48,21 @@ public class ProtoLogIntegrationTest {
@Test
public void testProtoLogToolIntegration() {
ProtoLogImpl mockedProtoLog = mock(ProtoLogImpl.class);
- runWith(mockedProtoLog, () -> {
- ProtoLogGroup.testProtoLog();
- });
+ runWith(mockedProtoLog, this::testProtoLog);
verify(mockedProtoLog).log(eq(ProtoLogImpl.LogLevel.ERROR), eq(ProtoLogGroup.TEST_GROUP),
anyInt(), eq(0b0010101001010111),
- eq(ProtoLogGroup.TEST_GROUP.isLogToLogcat()
+ eq(com.android.internal.protolog.ProtoLogGroup.TEST_GROUP.isLogToLogcat()
? "Test completed successfully: %b %d %o %x %e %g %f %% %s"
: null),
eq(new Object[]{true, 1L, 2L, 3L, 0.4, 0.5, 0.6, "ok"}));
}
+ private void testProtoLog() {
+ ProtoLog.e(ProtoLogGroup.TEST_GROUP,
+ "Test completed successfully: %b %d %o %x %e %g %f %% %s.",
+ true, 1, 2, 3, 0.4, 0.5, 0.6, "ok");
+ }
+
/**
* Starts protolog for the duration of {@code runnable}, with a ProtoLogImpl instance installed.
*/
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 0e1d4dc4aa0d..982e469cba92 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -568,7 +568,9 @@ public class SizeCompatTests extends WindowTestsBase {
private static WindowState addWindowToActivity(ActivityRecord activity) {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
- final WindowTestUtils.TestWindowState w = new WindowTestUtils.TestWindowState(
+ params.setFitInsetsSides(0);
+ params.setFitInsetsTypes(0);
+ final TestWindowState w = new TestWindowState(
activity.mWmService, mock(Session.class), new TestIWindow(), params, activity);
WindowTestsBase.makeWindowVisible(w);
w.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
@@ -581,7 +583,7 @@ public class SizeCompatTests extends WindowTestsBase {
doReturn(true).when(displayPolicy).hasStatusBar();
displayPolicy.onConfigurationChanged();
- final WindowTestUtils.TestWindowToken token = WindowTestUtils.createTestWindowToken(
+ final TestWindowToken token = createTestWindowToken(
WindowManager.LayoutParams.TYPE_STATUS_BAR, displayContent);
final WindowManager.LayoutParams attrs =
new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_STATUS_BAR);
@@ -589,7 +591,7 @@ public class SizeCompatTests extends WindowTestsBase {
attrs.layoutInDisplayCutoutMode =
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
attrs.setFitInsetsTypes(0 /* types */);
- final WindowTestUtils.TestWindowState statusBar = new WindowTestUtils.TestWindowState(
+ final TestWindowState statusBar = new TestWindowState(
displayContent.mWmService, mock(Session.class), new TestIWindow(), attrs, token);
token.addWindow(statusBar);
statusBar.setRequestedSize(displayContent.mBaseDisplayWidth,
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
index 3492556b3682..260f1e9a9259 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
@@ -76,8 +76,7 @@ public class TaskDisplayAreaTests extends WindowTestsBase {
// Stack should contain visible app window to be considered visible.
final Task pinnedTask = createTaskInStack(mPinnedStack, 0 /* userId */);
assertFalse(mPinnedStack.isVisible());
- final ActivityRecord pinnedApp =
- WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ final ActivityRecord pinnedApp = createTestActivityRecord(mDisplayContent);
pinnedTask.addChild(pinnedApp, 0 /* addPos */);
assertTrue(mPinnedStack.isVisible());
}
@@ -92,7 +91,7 @@ public class TaskDisplayAreaTests extends WindowTestsBase {
final Task stack = createTaskStackOnDisplay(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
task.addChild(activity, 0 /* addPos */);
final TaskDisplayArea taskDisplayArea = activity.getDisplayArea();
activity.mNeedsAnimationBoundsLayer = true;
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 205b842253b7..7cf30c0c9f35 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -85,14 +85,12 @@ public class TaskStackTests extends WindowTestsBase {
public void testClosingAppDifferentStackOrientation() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack, 0 /* userId */);
- ActivityRecord activity1 =
- WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity1 = createTestActivityRecord(mDisplayContent);
task1.addChild(activity1, 0);
activity1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
final Task task2 = createTaskInStack(stack, 1 /* userId */);
- ActivityRecord activity2=
- WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity2 = createTestActivityRecord(mDisplayContent);
task2.addChild(activity2, 0);
activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
@@ -105,14 +103,12 @@ public class TaskStackTests extends WindowTestsBase {
public void testMoveTaskToBackDifferentStackOrientation() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack, 0 /* userId */);
- ActivityRecord activity1 =
- WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity1 = createTestActivityRecord(mDisplayContent);
task1.addChild(activity1, 0);
activity1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
final Task task2 = createTaskInStack(stack, 1 /* userId */);
- ActivityRecord activity2 =
- WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity2 = createTestActivityRecord(mDisplayContent);
task2.addChild(activity2, 0);
activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
assertEquals(SCREEN_ORIENTATION_PORTRAIT, stack.getOrientation());
@@ -221,7 +217,7 @@ public class TaskStackTests extends WindowTestsBase {
public void testActivityAndTaskGetsProperType() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack, 0 /* userId */);
- ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity1 = createTestActivityRecord(mDisplayContent);
// First activity should become standard
task1.addChild(activity1, 0);
@@ -229,7 +225,7 @@ public class TaskStackTests extends WindowTestsBase {
assertEquals(WindowConfiguration.ACTIVITY_TYPE_STANDARD, task1.getActivityType());
// Second activity should also become standard
- ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity2 = createTestActivityRecord(mDisplayContent);
task1.addChild(activity2, WindowContainer.POSITION_TOP);
assertEquals(WindowConfiguration.ACTIVITY_TYPE_STANDARD, activity2.getActivityType());
assertEquals(WindowConfiguration.ACTIVITY_TYPE_STANDARD, task1.getActivityType());
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 92b6e6ef8ec9..ace0400bc293 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -56,8 +56,7 @@ public class TaskTests extends WindowTestsBase {
public void testRemoveContainer() {
final Task stackController1 = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stackController1, 0 /* userId */);
- final ActivityRecord activity =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity = createActivityRecordInTask(mDisplayContent, task);
task.removeIfPossible();
// Assert that the container was removed.
@@ -70,8 +69,7 @@ public class TaskTests extends WindowTestsBase {
public void testRemoveContainer_deferRemoval() {
final Task stackController1 = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stackController1, 0 /* userId */);
- final ActivityRecord activity =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity = createActivityRecordInTask(mDisplayContent, task);
doReturn(true).when(task).shouldDeferRemoval();
@@ -153,10 +151,8 @@ public class TaskTests extends WindowTestsBase {
public void testIsInStack() {
final Task task1 = createTaskStackOnDisplay(mDisplayContent);
final Task task2 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity1 =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task1);
- final ActivityRecord activity2 =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task2);
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task1);
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task2);
assertEquals(activity1, task1.isInTask(activity1));
assertNull(task1.isInTask(activity2));
}
@@ -165,12 +161,9 @@ public class TaskTests extends WindowTestsBase {
public void testRemoveChildForOverlayTask() {
final Task task = createTaskStackOnDisplay(mDisplayContent);
final int taskId = task.mTaskId;
- final ActivityRecord activity1 =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
- final ActivityRecord activity2 =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
- final ActivityRecord activity3 =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity3 = createActivityRecordInTask(mDisplayContent, task);
activity1.setTaskOverlay(true);
activity2.setTaskOverlay(true);
activity3.setTaskOverlay(true);
diff --git a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 75ed928b08a0..6ed762283524 100644
--- a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -44,7 +44,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testFlow() {
- final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(activity);
mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(activity);
@@ -56,8 +56,8 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testMultiple() {
- final ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(mDisplayContent);
- final ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity1 = createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity2 = createTestActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity1);
mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(activity1);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity2);
@@ -72,7 +72,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testClear() {
- final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
mDisplayContent.mUnknownAppVisibilityController.clear();
assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
@@ -80,7 +80,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testRemoveFinishingInvisibleActivityFromUnknown() {
- final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
activity.finishing = true;
activity.mVisibleRequested = true;
@@ -90,7 +90,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testAppRemoved() {
- final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(activity);
assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index 8ac44f2afcfd..4163a9a546a0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -810,8 +810,7 @@ public class WindowContainerTests extends WindowTestsBase {
public void testOnDisplayChanged() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity = createActivityRecordInTask(mDisplayContent, task);
final DisplayContent newDc = createNewDisplay();
stack.getDisplayArea().removeStack(stack);
@@ -854,19 +853,17 @@ public class WindowContainerTests extends WindowTestsBase {
public void testTaskCanApplyAnimation() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity2 =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
- final ActivityRecord activity1 =
- WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task);
verifyWindowContainerApplyAnimation(task, activity1, activity2);
}
@Test
public void testStackCanApplyAnimation() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(mDisplayContent,
+ final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent,
createTaskInStack(stack, 0 /* userId */));
- final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(mDisplayContent,
+ final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent,
createTaskInStack(stack, 0 /* userId */));
verifyWindowContainerApplyAnimation(stack, activity1, activity2);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index 8cfa4f00c8b6..91352972e772 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -931,8 +931,7 @@ public class WindowOrganizerTests extends WindowTestsBase {
final Task stack = createStack();
final Task task = createTask(stack);
- final ActivityRecord record = WindowTestUtils.createActivityRecordInTask(
- stack.mDisplayContent, task);
+ final ActivityRecord record = createActivityRecordInTask(stack.mDisplayContent, task);
stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
record.setTaskDescription(new ActivityManager.TaskDescription("TestDescription"));
@@ -966,8 +965,7 @@ public class WindowOrganizerTests extends WindowTestsBase {
public void testInterceptBackPressedOnTaskRoot() throws RemoteException {
final Task stack = createStack();
final Task task = createTask(stack);
- final ActivityRecord activity = WindowTestUtils.createActivityRecordInTask(
- stack.mDisplayContent, task);
+ final ActivityRecord activity = createActivityRecordInTask(stack.mDisplayContent, task);
final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
// Setup the task to be controlled by the MW mode organizer
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index 2f736555ae1b..189e540af0ca 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.Display.INVALID_DISPLAY;
@@ -253,6 +255,19 @@ public class WindowProcessControllerTests extends WindowTestsBase {
assertFalse(mWpc.registeredForActivityConfigChanges());
}
+ @Test
+ public void testProcessLevelConfiguration() {
+ Configuration config = new Configuration();
+ config.windowConfiguration.setActivityType(ACTIVITY_TYPE_HOME);
+ mWpc.onRequestedOverrideConfigurationChanged(config);
+ assertEquals(ACTIVITY_TYPE_HOME, config.windowConfiguration.getActivityType());
+ assertEquals(ACTIVITY_TYPE_UNDEFINED, mWpc.getActivityType());
+
+ mWpc.onMergedOverrideConfigurationChanged(config);
+ assertEquals(ACTIVITY_TYPE_HOME, config.windowConfiguration.getActivityType());
+ assertEquals(ACTIVITY_TYPE_UNDEFINED, mWpc.getActivityType());
+ }
+
private TestDisplayContent createTestDisplayContentInContainer() {
return new TestDisplayContent.Builder(mAtm, 1000, 1500).build();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 3894a2eaa461..f095fd42900b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -357,8 +357,7 @@ public class WindowStateTests extends WindowTestsBase {
// Call prepareWindowToDisplayDuringRelayout for a windows that are not children of an
// activity. Both windows have the FLAG_TURNS_SCREEN_ON so both should call wakeup
- final WindowToken windowToken = WindowTestUtils.createTestWindowToken(FIRST_SUB_WINDOW,
- mDisplayContent);
+ final WindowToken windowToken = createTestWindowToken(FIRST_SUB_WINDOW, mDisplayContent);
final WindowState firstWindow = createWindow(null, TYPE_APPLICATION, windowToken,
"firstWindow");
final WindowState secondWindow = createWindow(null, TYPE_APPLICATION, windowToken,
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
deleted file mode 100644
index 0180d87290a1..000000000000
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import static android.app.AppOpsManager.OP_NONE;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
-
-import android.os.IBinder;
-import android.view.IWindow;
-import android.view.WindowManager;
-
-import com.android.server.wm.WindowTestsBase.ActivityBuilder;
-
-/**
- * A collection of static functions that provide access to WindowManager related test functionality.
- */
-class WindowTestUtils {
-
- /** Creates a {@link Task} and adds it to the specified {@link Task}. */
- static Task createTaskInStack(WindowManagerService service, Task stack, int userId) {
- final Task task = new WindowTestsBase.TaskBuilder(stack.mStackSupervisor)
- .setUserId(userId)
- .setStack(stack)
- .build();
- return task;
- }
-
- /** Creates an {@link ActivityRecord} and adds it to the specified {@link Task}. */
- static ActivityRecord createActivityRecordInTask(DisplayContent dc, Task task) {
- final ActivityRecord activity = createTestActivityRecord(dc);
- task.addChild(activity, POSITION_TOP);
- return activity;
- }
-
- static ActivityRecord createTestActivityRecord(Task stack) {
- final ActivityRecord activity = new ActivityBuilder(stack.mAtmService)
- .setStack(stack)
- .setCreateTask(true)
- .build();
- postCreateActivitySetup(activity, stack.getDisplayContent());
- return activity;
- }
-
- static ActivityRecord createTestActivityRecord(DisplayContent dc) {
- final ActivityRecord activity = new ActivityBuilder(dc.mWmService.mAtmService).build();
- postCreateActivitySetup(activity, dc);
- return activity;
- }
-
- private static void postCreateActivitySetup(ActivityRecord activity, DisplayContent dc) {
- activity.onDisplayChanged(dc);
- activity.setOccludesParent(true);
- activity.setVisible(true);
- activity.mVisibleRequested = true;
- }
-
- static TestWindowToken createTestWindowToken(int type, DisplayContent dc) {
- return createTestWindowToken(type, dc, false /* persistOnEmpty */);
- }
-
- static TestWindowToken createTestWindowToken(int type, DisplayContent dc,
- boolean persistOnEmpty) {
- SystemServicesTestRule.checkHoldsLock(dc.mWmService.mGlobalLock);
-
- return new TestWindowToken(type, dc, persistOnEmpty);
- }
-
- /* Used so we can gain access to some protected members of the {@link WindowToken} class */
- static class TestWindowToken extends WindowToken {
-
- private TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
- super(dc.mWmService, mock(IBinder.class), type, persistOnEmpty, dc,
- false /* ownerCanManageAppTokens */);
- }
-
- int getWindowsCount() {
- return mChildren.size();
- }
-
- boolean hasWindow(WindowState w) {
- return mChildren.contains(w);
- }
- }
-
- /** Used to track resize reports. */
- static class TestWindowState extends WindowState {
- boolean mResizeReported;
-
- TestWindowState(WindowManagerService service, Session session, IWindow window,
- WindowManager.LayoutParams attrs, WindowToken token) {
- super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0, 0,
- false /* ownerCanAddInternalSystemWindow */);
- }
-
- @Override
- void reportResized() {
- super.reportResized();
- mResizeReported = true;
- }
-
- @Override
- public boolean isGoneForLayoutLw() {
- return false;
- }
-
- @Override
- void updateResizingWindowIfNeeded() {
- // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
- // the system that it can actually update the window.
- boolean hadSurface = mHasSurface;
- mHasSurface = true;
-
- super.updateResizingWindowIfNeeded();
-
- mHasSurface = hadSurface;
- }
- }
-}
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 ec19a58b17c4..5ce61b4e4916 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -47,6 +47,7 @@ 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.spyOn;
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -66,6 +67,7 @@ import android.content.res.Configuration;
import android.hardware.display.DisplayManager;
import android.os.Build;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.service.voice.IVoiceInteractionSession;
@@ -239,7 +241,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
private WindowToken createWindowToken(
DisplayContent dc, int windowingMode, int activityType, int type) {
if (type < FIRST_APPLICATION_WINDOW || type > LAST_APPLICATION_WINDOW) {
- return WindowTestUtils.createTestWindowToken(type, dc);
+ return createTestWindowToken(type, dc);
}
return createActivityRecord(dc, windowingMode, activityType);
@@ -249,10 +251,39 @@ class WindowTestsBase extends SystemServiceTestsBase {
return createTestActivityRecord(dc, windowingMode, activityType);
}
- ActivityRecord createTestActivityRecord(DisplayContent dc, int
- windowingMode, int activityType) {
+ ActivityRecord createTestActivityRecord(DisplayContent dc, int windowingMode,
+ int activityType) {
final Task stack = createTaskStackOnDisplay(windowingMode, activityType, dc);
- return WindowTestUtils.createTestActivityRecord(stack);
+ return createTestActivityRecord(stack);
+ }
+
+ /** Creates an {@link ActivityRecord} and adds it to the specified {@link Task}. */
+ static ActivityRecord createActivityRecordInTask(DisplayContent dc, Task task) {
+ final ActivityRecord activity = createTestActivityRecord(dc);
+ task.addChild(activity, POSITION_TOP);
+ return activity;
+ }
+
+ static ActivityRecord createTestActivityRecord(DisplayContent dc) {
+ final ActivityRecord activity = new ActivityBuilder(dc.mWmService.mAtmService).build();
+ postCreateActivitySetup(activity, dc);
+ return activity;
+ }
+
+ static ActivityRecord createTestActivityRecord(Task stack) {
+ final ActivityRecord activity = new ActivityBuilder(stack.mAtmService)
+ .setStack(stack)
+ .setCreateTask(true)
+ .build();
+ postCreateActivitySetup(activity, stack.getDisplayContent());
+ return activity;
+ }
+
+ private static void postCreateActivitySetup(ActivityRecord activity, DisplayContent dc) {
+ activity.onDisplayChanged(dc);
+ activity.setOccludesParent(true);
+ activity.setVisible(true);
+ activity.mVisibleRequested = true;
}
WindowState createWindow(WindowState parent, int type, String name) {
@@ -274,8 +305,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
}
WindowState createAppWindow(Task task, int type, String name) {
- final ActivityRecord activity =
- WindowTestUtils.createTestActivityRecord(task.getDisplayContent());
+ final ActivityRecord activity = createTestActivityRecord(task.getDisplayContent());
task.addChild(activity, 0);
return createWindow(null, type, activity, name);
}
@@ -390,7 +420,11 @@ class WindowTestsBase extends SystemServiceTestsBase {
/** Creates a {@link Task} and adds it to the specified {@link Task}. */
Task createTaskInStack(Task stack, int userId) {
- return WindowTestUtils.createTaskInStack(mWm, stack, userId);
+ final Task task = new TaskBuilder(stack.mStackSupervisor)
+ .setUserId(userId)
+ .setStack(stack)
+ .build();
+ return task;
}
/** Creates a {@link DisplayContent} that supports IME and adds it to the system. */
@@ -432,12 +466,11 @@ class WindowTestsBase extends SystemServiceTestsBase {
return createNewDisplay(displayInfo, true /* supportIme */);
}
- /** Creates a {@link com.android.server.wm.WindowTestUtils.TestWindowState} */
- WindowTestUtils.TestWindowState createWindowState(WindowManager.LayoutParams attrs,
- WindowToken token) {
+ /** Creates a {@link TestWindowState} */
+ TestWindowState createWindowState(WindowManager.LayoutParams attrs, WindowToken token) {
SystemServicesTestRule.checkHoldsLock(mWm.mGlobalLock);
- return new WindowTestUtils.TestWindowState(mWm, mMockSession, mIWindow, attrs, token);
+ return new TestWindowState(mWm, mMockSession, mIWindow, attrs, token);
}
/** Creates a {@link DisplayContent} as parts of simulate display info for test. */
@@ -1055,4 +1088,66 @@ class WindowTestsBase extends SystemServiceTestsBase {
public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) {
}
}
+
+ static TestWindowToken createTestWindowToken(int type, DisplayContent dc) {
+ return createTestWindowToken(type, dc, false /* persistOnEmpty */);
+ }
+
+ static TestWindowToken createTestWindowToken(int type, DisplayContent dc,
+ boolean persistOnEmpty) {
+ SystemServicesTestRule.checkHoldsLock(dc.mWmService.mGlobalLock);
+
+ return new TestWindowToken(type, dc, persistOnEmpty);
+ }
+
+ /** Used so we can gain access to some protected members of the {@link WindowToken} class */
+ static class TestWindowToken extends WindowToken {
+
+ private TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
+ super(dc.mWmService, mock(IBinder.class), type, persistOnEmpty, dc,
+ false /* ownerCanManageAppTokens */);
+ }
+
+ int getWindowsCount() {
+ return mChildren.size();
+ }
+
+ boolean hasWindow(WindowState w) {
+ return mChildren.contains(w);
+ }
+ }
+
+ /** Used to track resize reports. */
+ static class TestWindowState extends WindowState {
+ boolean mResizeReported;
+
+ TestWindowState(WindowManagerService service, Session session, IWindow window,
+ WindowManager.LayoutParams attrs, WindowToken token) {
+ super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0, 0,
+ false /* ownerCanAddInternalSystemWindow */);
+ }
+
+ @Override
+ void reportResized() {
+ super.reportResized();
+ mResizeReported = true;
+ }
+
+ @Override
+ public boolean isGoneForLayoutLw() {
+ return false;
+ }
+
+ @Override
+ void updateResizingWindowIfNeeded() {
+ // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
+ // the system that it can actually update the window.
+ boolean hadSurface = mHasSurface;
+ mHasSurface = true;
+
+ super.updateResizingWindowIfNeeded();
+
+ mHasSurface = hadSurface;
+ }
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
index f185da395754..e0785c13a336 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
@@ -27,6 +27,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -58,8 +59,7 @@ public class WindowTokenTests extends WindowTestsBase {
@Test
public void testAddWindow() {
- final WindowTestUtils.TestWindowToken token =
- WindowTestUtils.createTestWindowToken(0, mDisplayContent);
+ final TestWindowToken token = createTestWindowToken(0, mDisplayContent);
assertEquals(0, token.getWindowsCount());
@@ -93,7 +93,7 @@ public class WindowTokenTests extends WindowTestsBase {
@Test
public void testChildRemoval() {
final DisplayContent dc = mDisplayContent;
- final WindowTestUtils.TestWindowToken token = WindowTestUtils.createTestWindowToken(0, dc);
+ final TestWindowToken token = createTestWindowToken(0, dc);
assertEquals(token, dc.getWindowToken(token.token));
@@ -116,7 +116,7 @@ public class WindowTokenTests extends WindowTestsBase {
*/
@Test
public void testTokenRemovalProcess() {
- final WindowTestUtils.TestWindowToken token = WindowTestUtils.createTestWindowToken(
+ final TestWindowToken token = createTestWindowToken(
TYPE_TOAST, mDisplayContent, true /* persistOnEmpty */);
// Verify that the token is on the display
@@ -146,29 +146,40 @@ public class WindowTokenTests extends WindowTestsBase {
assertEquals(0, token.getWindowsCount());
}
- @UseTestDisplay(addWindows = { W_ACTIVITY, W_WALLPAPER })
@Test
public void testFinishFixedRotationTransform() {
- final WindowToken appToken = mAppWindow.mToken;
- final WindowToken wallpaperToken = mWallpaperWindow.mToken;
+ final WindowToken[] tokens = new WindowToken[3];
+ for (int i = 0; i < tokens.length; i++) {
+ tokens[i] = createTestWindowToken(TYPE_APPLICATION_OVERLAY, mDisplayContent);
+ }
+
final Configuration config = new Configuration(mDisplayContent.getConfiguration());
final int originalRotation = config.windowConfiguration.getRotation();
final int targetRotation = (originalRotation + 1) % 4;
config.windowConfiguration.setRotation(targetRotation);
- appToken.applyFixedRotationTransform(mDisplayInfo, mDisplayContent.mDisplayFrames, config);
- wallpaperToken.linkFixedRotationTransform(appToken);
+ tokens[0].applyFixedRotationTransform(mDisplayInfo, mDisplayContent.mDisplayFrames, config);
+ tokens[1].linkFixedRotationTransform(tokens[0]);
// The window tokens should apply the rotation by the transformation.
- assertEquals(targetRotation, appToken.getWindowConfiguration().getRotation());
- assertEquals(targetRotation, wallpaperToken.getWindowConfiguration().getRotation());
+ assertEquals(targetRotation, tokens[0].getWindowConfiguration().getRotation());
+ assertEquals(targetRotation, tokens[1].getWindowConfiguration().getRotation());
+
+ tokens[2].applyFixedRotationTransform(mDisplayInfo, mDisplayContent.mDisplayFrames, config);
+ // The tokens[1] was linked to tokens[0], this should make tokens[1] link to tokens[2].
+ tokens[1].linkFixedRotationTransform(tokens[2]);
+
+ // Assume the display doesn't rotate, the transformation will be canceled.
+ tokens[0].finishFixedRotationTransform();
- // The display doesn't rotate, the transformation will be canceled.
- mAppWindow.mToken.finishFixedRotationTransform();
+ // The tokens[0] should restore to the original rotation.
+ assertEquals(originalRotation, tokens[0].getWindowConfiguration().getRotation());
+ // The tokens[1] is linked to tokens[2], it should keep the target rotation.
+ assertNotEquals(originalRotation, tokens[1].getWindowConfiguration().getRotation());
- // The window tokens should restore to the original rotation.
- assertEquals(originalRotation, appToken.getWindowConfiguration().getRotation());
- assertEquals(originalRotation, wallpaperToken.getWindowConfiguration().getRotation());
+ tokens[2].finishFixedRotationTransform();
+ // The rotation of tokens[1] should be restored because its linked state is finished.
+ assertEquals(originalRotation, tokens[1].getWindowConfiguration().getRotation());
}
/**
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 0f898f8e679e..9ff44eba8fa0 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -967,10 +967,10 @@ public class VoiceInteractionManagerService extends SystemService {
throw new IllegalArgumentException("Illegal argument(s) in getKeyphraseSoundModel");
}
- final int callingUid = UserHandle.getCallingUserId();
+ final int callingUserId = UserHandle.getCallingUserId();
final long caller = Binder.clearCallingIdentity();
try {
- return mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
+ return mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUserId, bcp47Locale);
} finally {
Binder.restoreCallingIdentity(caller);
}
@@ -1010,7 +1010,7 @@ public class VoiceInteractionManagerService extends SystemService {
"Illegal argument(s) in deleteKeyphraseSoundModel");
}
- final int callingUid = UserHandle.getCallingUserId();
+ final int callingUserId = UserHandle.getCallingUserId();
final long caller = Binder.clearCallingIdentity();
boolean deleted = false;
try {
@@ -1018,7 +1018,8 @@ public class VoiceInteractionManagerService extends SystemService {
if (unloadStatus != SoundTriggerInternal.STATUS_OK) {
Slog.w(TAG, "Unable to unload keyphrase sound model:" + unloadStatus);
}
- deleted = mDbHelper.deleteKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
+ deleted = mDbHelper.deleteKeyphraseSoundModel(
+ keyphraseId, callingUserId, bcp47Locale);
return deleted ? SoundTriggerInternal.STATUS_OK : SoundTriggerInternal.STATUS_ERROR;
} finally {
if (deleted) {
@@ -1045,11 +1046,11 @@ public class VoiceInteractionManagerService extends SystemService {
throw new IllegalArgumentException("Illegal argument(s) in isEnrolledForKeyphrase");
}
- final int callingUid = UserHandle.getCallingUserId();
+ final int callingUserId = UserHandle.getCallingUserId();
final long caller = Binder.clearCallingIdentity();
try {
KeyphraseSoundModel model =
- mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
+ mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUserId, bcp47Locale);
return model != null;
} finally {
Binder.restoreCallingIdentity(caller);
@@ -1067,11 +1068,11 @@ public class VoiceInteractionManagerService extends SystemService {
throw new IllegalArgumentException("Illegal argument(s) in isEnrolledForKeyphrase");
}
- final int callingUid = UserHandle.getCallingUserId();
+ final int callingUserId = UserHandle.getCallingUserId();
final long caller = Binder.clearCallingIdentity();
try {
KeyphraseSoundModel model =
- mDbHelper.getKeyphraseSoundModel(keyphrase, callingUid, bcp47Locale);
+ mDbHelper.getKeyphraseSoundModel(keyphrase, callingUserId, bcp47Locale);
if (model == null) {
return null;
}
@@ -1118,11 +1119,11 @@ public class VoiceInteractionManagerService extends SystemService {
}
}
- int callingUid = UserHandle.getCallingUserId();
+ final int callingUserId = UserHandle.getCallingUserId();
final long caller = Binder.clearCallingIdentity();
try {
KeyphraseSoundModel soundModel =
- mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUid, bcp47Locale);
+ mDbHelper.getKeyphraseSoundModel(keyphraseId, callingUserId, bcp47Locale);
if (soundModel == null
|| soundModel.getUuid() == null
|| soundModel.getKeyphrases() == null) {
diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
index e57b03098758..d4308c4c30ad 100644
--- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -74,7 +75,7 @@ public final class CarrierAppUtils {
* privileged apps may have changed.
*/
public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage,
- TelephonyManager telephonyManager, int userId, Context context) {
+ TelephonyManager telephonyManager, @UserIdInt int userId, Context context) {
if (DEBUG) {
Log.d(TAG, "disableCarrierAppsUntilPrivileged");
}
@@ -101,7 +102,7 @@ public final class CarrierAppUtils {
* Manager can kill it, and this can lead to crashes as the app is in an unexpected state.
*/
public static synchronized void disableCarrierAppsUntilPrivileged(String callingPackage,
- int userId, Context context) {
+ @UserIdInt int userId, Context context) {
if (DEBUG) {
Log.d(TAG, "disableCarrierAppsUntilPrivileged");
}
@@ -117,9 +118,9 @@ public final class CarrierAppUtils {
systemCarrierAssociatedAppsDisabledUntilUsed, context);
}
- private static ContentResolver getContentResolverForUser(Context context, int userId) {
- Context userContext = context.createContextAsUser(UserHandle.getUserHandleForUid(userId),
- 0);
+ private static ContentResolver getContentResolverForUser(Context context,
+ @UserIdInt int userId) {
+ Context userContext = context.createContextAsUser(UserHandle.of(userId), 0);
return userContext.getContentResolver();
}
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 2b2608724e12..78dc377a303c 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -46,6 +46,7 @@ import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.ISms;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.SmsRawData;
+import com.android.telephony.Rlog;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -1953,7 +1954,6 @@ public final class SmsManager {
public boolean enableCellBroadcastRange(int startMessageId, int endMessageId,
@android.telephony.SmsCbMessage.MessageFormat int ranType) {
boolean success = false;
-
if (endMessageId < startMessageId) {
throw new IllegalArgumentException("endMessageId < startMessageId");
}
@@ -1962,10 +1962,14 @@ public final class SmsManager {
if (iSms != null) {
// If getSubscriptionId() returns INVALID or an inactive subscription, we will use
// the default phone internally.
- success = iSms.enableCellBroadcastRangeForSubscriber(getSubscriptionId(),
+ int subId = getSubscriptionId();
+ success = iSms.enableCellBroadcastRangeForSubscriber(subId,
startMessageId, endMessageId, ranType);
+ Rlog.d(TAG, "enableCellBroadcastRange: " + (success ? "succeeded" : "failed")
+ + " at calling enableCellBroadcastRangeForSubscriber. subId = " + subId);
}
} catch (RemoteException ex) {
+ Rlog.d(TAG, "enableCellBroadcastRange: " + ex.getStackTrace());
// ignore it
}
@@ -2019,10 +2023,14 @@ public final class SmsManager {
if (iSms != null) {
// If getSubscriptionId() returns INVALID or an inactive subscription, we will use
// the default phone internally.
- success = iSms.disableCellBroadcastRangeForSubscriber(getSubscriptionId(),
+ int subId = getSubscriptionId();
+ success = iSms.disableCellBroadcastRangeForSubscriber(subId,
startMessageId, endMessageId, ranType);
+ Rlog.d(TAG, "disableCellBroadcastRange: " + (success ? "succeeded" : "failed")
+ + " at calling disableCellBroadcastRangeForSubscriber. subId = " + subId);
}
} catch (RemoteException ex) {
+ Rlog.d(TAG, "disableCellBroadcastRange: " + ex.getStackTrace());
// ignore it
}
diff --git a/tests/Internal/Android.bp b/tests/Internal/Android.bp
index e233fed7e785..9da17db6a573 100644
--- a/tests/Internal/Android.bp
+++ b/tests/Internal/Android.bp
@@ -11,6 +11,7 @@ android_test {
"androidx.test.rules",
"mockito-target-minus-junit4",
"truth-prebuilt",
+ "platform-test-annotations",
],
java_resource_dirs: ["res"],
certificate: "platform",
diff --git a/services/tests/servicestests/src/com/android/server/protolog/ProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java
index 3e9f625ecdd9..3db011683a86 100644
--- a/services/tests/servicestests/src/com/android/server/protolog/ProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/ProtoLogImplTest.java
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-package com.android.server.protolog;
+package com.android.internal.protolog;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static com.android.server.protolog.ProtoLogImpl.PROTOLOG_VERSION;
+import static com.android.internal.protolog.ProtoLogImpl.PROTOLOG_VERSION;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -42,7 +42,7 @@ import android.util.proto.ProtoInputStream;
import androidx.test.filters.SmallTest;
-import com.android.server.protolog.common.IProtoLogGroup;
+import com.android.internal.protolog.common.IProtoLogGroup;
import org.junit.After;
import org.junit.Before;
diff --git a/services/tests/servicestests/src/com/android/server/protolog/ProtoLogViewerConfigReaderTest.java b/tests/Internal/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java
index 02540559fbd0..ae5021638745 100644
--- a/services/tests/servicestests/src/com/android/server/protolog/ProtoLogViewerConfigReaderTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.protolog;
+package com.android.internal.protolog;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
diff --git a/services/tests/servicestests/src/com/android/server/protolog/common/LogDataTypeTest.java b/tests/Internal/src/com/android/internal/protolog/common/LogDataTypeTest.java
index 4c7f5fdc821c..e20ca3df57c7 100644
--- a/services/tests/servicestests/src/com/android/server/protolog/common/LogDataTypeTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/common/LogDataTypeTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.protolog.common;
+package com.android.internal.protolog.common;
import static org.junit.Assert.assertEquals;
diff --git a/tests/RollbackTest/README.txt b/tests/RollbackTest/README.txt
index c0b718a3e2c1..bc3b3bc3a1ee 100644
--- a/tests/RollbackTest/README.txt
+++ b/tests/RollbackTest/README.txt
@@ -9,10 +9,10 @@ StagedRollbackTest
- device driven test for staged rollbacks.
TestApp
- - source for dummy apks used in testing.
+ - source for fake apks used in testing.
TestApex
- - source for dummy apex modules used in testing.
+ - source for fake apex modules used in testing.
Running the tests
=================
diff --git a/tests/StagedInstallTest/Android.bp b/tests/StagedInstallTest/Android.bp
index 530d0e492f2e..76f8df02465b 100644
--- a/tests/StagedInstallTest/Android.bp
+++ b/tests/StagedInstallTest/Android.bp
@@ -18,6 +18,9 @@ android_test_helper_app {
srcs: ["app/src/**/*.java"],
static_libs: ["androidx.test.rules", "cts-install-lib"],
test_suites: ["general-tests"],
+ java_resources: [
+ ":com.android.apex.apkrollback.test_v2",
+ ],
}
java_test_host {
diff --git a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
index 02597d548361..12f1750fb78c 100644
--- a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
@@ -49,6 +49,11 @@ import java.util.function.Consumer;
public class StagedInstallInternalTest {
private static final String TAG = StagedInstallInternalTest.class.getSimpleName();
+ private static final String APK_IN_APEX_TESTAPEX_NAME = "com.android.apex.apkrollback.test";
+ private static final TestApp TEST_APEX_WITH_APK_V1 = new TestApp("TestApexWithApkV1",
+ APK_IN_APEX_TESTAPEX_NAME, 1, /*isApex*/true, APK_IN_APEX_TESTAPEX_NAME + "_v1.apex");
+ private static final TestApp TEST_APEX_WITH_APK_V2 = new TestApp("TestApexWithApkV2",
+ APK_IN_APEX_TESTAPEX_NAME, 2, /*isApex*/true, APK_IN_APEX_TESTAPEX_NAME + "_v2.apex");
private File mTestStateFile = new File(
InstrumentationRegistry.getInstrumentation().getContext().getFilesDir(),
@@ -82,6 +87,24 @@ public class StagedInstallInternalTest {
}
@Test
+ public void testDuplicateApkInApexShouldFail_Commit() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
+ // Duplicate packages(TestApp.A) in TEST_APEX_WITH_APK_V2(apk-in-apex) and TestApp.A2(apk)
+ // should fail to install.
+ int sessionId = Install.multi(TEST_APEX_WITH_APK_V2, TestApp.A2).setStaged().commit();
+ storeSessionId(sessionId);
+ }
+
+ @Test
+ public void testDuplicateApkInApexShouldFail_Verify() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
+ int sessionId = retrieveLastSessionId();
+ PackageInstaller.SessionInfo info =
+ InstallUtils.getPackageInstaller().getSessionInfo(sessionId);
+ assertThat(info.isStagedSessionFailed()).isTrue();
+ }
+
+ @Test
public void testSystemServerRestartDoesNotAffectStagedSessions_Commit() throws Exception {
int sessionId = Install.single(TestApp.A1).setStaged().commit();
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
diff --git a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
index 5285b04f67d7..792e29d93be2 100644
--- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
@@ -22,12 +22,16 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
-import com.android.cts.install.lib.host.InstallUtilsHost;
+import android.cts.install.lib.host.InstallUtilsHost;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.ddmlib.Log;
import com.android.tests.rollback.host.AbandonSessionsRule;
import com.android.tests.util.ModuleTestUtils;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.util.CommandResult;
+import com.android.tradefed.util.CommandStatus;
import com.android.tradefed.util.ProcessInfo;
import org.junit.After;
@@ -48,6 +52,7 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
public AbandonSessionsRule mHostTestRule = new AbandonSessionsRule(this);
private static final String SHIM_V2 = "com.android.apex.cts.shim.v2.apex";
private static final String APK_A = "TestAppAv1.apk";
+ private static final String APK_IN_APEX_TESTAPEX_NAME = "com.android.apex.apkrollback.test";
private final ModuleTestUtils mTestUtils = new ModuleTestUtils(this);
private final InstallUtilsHost mHostUtils = new InstallUtilsHost(this);
@@ -73,6 +78,8 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
} catch (AssertionError e) {
Log.e(TAG, e);
}
+ deleteFiles("/system/apex/" + APK_IN_APEX_TESTAPEX_NAME + "*.apex",
+ "/data/apex/active/" + APK_IN_APEX_TESTAPEX_NAME + "*.apex");
}
@Before
@@ -85,6 +92,55 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
cleanUp();
}
+ /**
+ * Deletes files and reboots the device if necessary.
+ * @param files the paths of files which might contain wildcards
+ */
+ private void deleteFiles(String... files) throws Exception {
+ boolean found = false;
+ for (String file : files) {
+ CommandResult result = getDevice().executeShellV2Command("ls " + file);
+ if (result.getStatus() == CommandStatus.SUCCESS) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found) {
+ if (!getDevice().isAdbRoot()) {
+ getDevice().enableAdbRoot();
+ }
+ getDevice().remountSystemWritable();
+ for (String file : files) {
+ getDevice().executeShellCommand("rm -rf " + file);
+ }
+ getDevice().reboot();
+ }
+ }
+
+ private void pushTestApex() throws Exception {
+ CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild());
+ final String fileName = APK_IN_APEX_TESTAPEX_NAME + "_v1.apex";
+ final File apex = buildHelper.getTestFile(fileName);
+ if (!getDevice().isAdbRoot()) {
+ getDevice().enableAdbRoot();
+ }
+ getDevice().remountSystemWritable();
+ assertTrue(getDevice().pushFile(apex, "/system/apex/" + fileName));
+ getDevice().reboot();
+ }
+
+ /**
+ * Tests that duplicate packages in apk-in-apex and apk should fail to install.
+ */
+ @Test
+ public void testDuplicateApkInApexShouldFail() throws Exception {
+ pushTestApex();
+ runPhase("testDuplicateApkInApexShouldFail_Commit");
+ getDevice().reboot();
+ runPhase("testDuplicateApkInApexShouldFail_Verify");
+ }
+
@Test
public void testSystemServerRestartDoesNotAffectStagedSessions() throws Exception {
runPhase("testSystemServerRestartDoesNotAffectStagedSessions_Commit");
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index a384687e06f6..ab12ac0ef56e 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -28,11 +28,17 @@ import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRODUCT;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_VENDOR;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
+import static android.net.INetd.PERMISSION_INTERNET;
+import static android.net.INetd.PERMISSION_NONE;
+import static android.net.INetd.PERMISSION_SYSTEM;
+import static android.net.INetd.PERMISSION_UNINSTALLED;
+import static android.net.INetd.PERMISSION_UPDATE_DEVICE_STATS;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.os.Process.SYSTEM_UID;
import static com.android.server.connectivity.PermissionMonitor.NETWORK;
import static com.android.server.connectivity.PermissionMonitor.SYSTEM;
+import static com.android.server.connectivity.PermissionMonitor.UidNetdPermissionInfo;
import static junit.framework.Assert.fail;
@@ -63,7 +69,7 @@ import android.net.UidRange;
import android.os.Build;
import android.os.UserHandle;
import android.os.UserManager;
-import android.util.SparseIntArray;
+import android.util.SparseArray;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -312,7 +318,7 @@ public class PermissionMonitorTest {
// Add hook to verify and track result of setPermission.
doAnswer((InvocationOnMock invocation) -> {
final Object[] args = invocation.getArguments();
- final Boolean isSystem = args[0].equals(INetd.PERMISSION_SYSTEM);
+ final Boolean isSystem = args[0].equals(PERMISSION_SYSTEM);
for (final int uid : (int[]) args[1]) {
// TODO: Currently, permission monitor will send duplicate commands for each uid
// corresponding to each user. Need to fix that and uncomment below test.
@@ -555,39 +561,40 @@ public class PermissionMonitorTest {
// SYSTEM_UID1: SYSTEM_PACKAGE1 has internet permission and update device stats permission.
// SYSTEM_UID2: SYSTEM_PACKAGE2 has only update device stats permission.
- SparseIntArray netdPermissionsAppIds = new SparseIntArray();
- netdPermissionsAppIds.put(MOCK_UID1, INetd.PERMISSION_INTERNET);
- netdPermissionsAppIds.put(MOCK_UID2, INetd.PERMISSION_NONE);
- netdPermissionsAppIds.put(SYSTEM_UID1, INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS);
- netdPermissionsAppIds.put(SYSTEM_UID2, INetd.PERMISSION_UPDATE_DEVICE_STATS);
+ final SparseArray<UidNetdPermissionInfo> uidsPermInfo = new SparseArray<>();
+ uidsPermInfo.put(MOCK_UID1, new UidNetdPermissionInfo(PERMISSION_INTERNET));
+ uidsPermInfo.put(MOCK_UID2, new UidNetdPermissionInfo(PERMISSION_NONE));
+ uidsPermInfo.put(SYSTEM_UID1, new UidNetdPermissionInfo(
+ PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS));
+ uidsPermInfo.put(SYSTEM_UID2, new UidNetdPermissionInfo(PERMISSION_UPDATE_DEVICE_STATS));
// Send the permission information to netd, expect permission updated.
- mPermissionMonitor.sendPackagePermissionsToNetd(netdPermissionsAppIds);
+ mPermissionMonitor.sendPackagePermissionsToNetd(uidsPermInfo);
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET,
+ mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET,
new int[]{MOCK_UID1});
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{MOCK_UID2});
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{SYSTEM_UID1});
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UPDATE_DEVICE_STATS,
+ mNetdServiceMonitor.expectPermission(PERMISSION_NONE, new int[]{MOCK_UID2});
+ mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET
+ | PERMISSION_UPDATE_DEVICE_STATS, new int[]{SYSTEM_UID1});
+ mNetdServiceMonitor.expectPermission(PERMISSION_UPDATE_DEVICE_STATS,
new int[]{SYSTEM_UID2});
// Update permission of MOCK_UID1, expect new permission show up.
- mPermissionMonitor.sendPackagePermissionsForUid(MOCK_UID1,
- INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS);
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
+ mPermissionMonitor.sendPackagePermissionsForUid(MOCK_UID1, new UidNetdPermissionInfo(
+ PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS));
+ mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET
+ | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
// Change permissions of SYSTEM_UID2, expect new permission show up and old permission
// revoked.
- mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID2,
- INetd.PERMISSION_INTERNET);
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{SYSTEM_UID2});
+ mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID2, new UidNetdPermissionInfo(
+ PERMISSION_INTERNET));
+ mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{SYSTEM_UID2});
// Revoke permission from SYSTEM_UID1, expect no permission stored.
- mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID1, INetd.PERMISSION_NONE);
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{SYSTEM_UID1});
+ mPermissionMonitor.sendPackagePermissionsForUid(SYSTEM_UID1, new UidNetdPermissionInfo(
+ PERMISSION_NONE));
+ mNetdServiceMonitor.expectPermission(PERMISSION_NONE, new int[]{SYSTEM_UID1});
}
private PackageInfo setPackagePermissions(String packageName, int uid, String[] permissions)
@@ -611,11 +618,11 @@ public class PermissionMonitorTest {
final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService);
addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS});
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
+ mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET
+ | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
addPackage(MOCK_PACKAGE2, MOCK_UID2, new String[] {INTERNET});
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID2});
+ mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID2});
}
@Test
@@ -623,8 +630,8 @@ public class PermissionMonitorTest {
final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService);
addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS});
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
+ mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET
+ | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
// Install another package with the same uid and no permissions should not cause the UID to
// lose permissions.
@@ -633,8 +640,8 @@ public class PermissionMonitorTest {
when(mPackageManager.getPackagesForUid(MOCK_UID1))
.thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2});
mPermissionMonitor.onPackageAdded(MOCK_PACKAGE2, MOCK_UID1);
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
+ mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET
+ | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
}
@Test
@@ -642,12 +649,12 @@ public class PermissionMonitorTest {
final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService);
addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS});
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
+ mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET
+ | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{});
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1);
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[]{MOCK_UID1});
+ mNetdServiceMonitor.expectPermission(PERMISSION_UNINSTALLED, new int[]{MOCK_UID1});
}
@Test
@@ -655,16 +662,16 @@ public class PermissionMonitorTest {
final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService);
addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS});
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
+ mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET
+ | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{});
removeAllPermissions(MOCK_UID1);
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1);
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_UNINSTALLED, new int[]{MOCK_UID1});
+ mNetdServiceMonitor.expectPermission(PERMISSION_UNINSTALLED, new int[]{MOCK_UID1});
addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET});
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1});
+ mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID1});
}
@Test
@@ -672,10 +679,10 @@ public class PermissionMonitorTest {
final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService);
addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {});
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_NONE, new int[]{MOCK_UID1});
+ mNetdServiceMonitor.expectPermission(PERMISSION_NONE, new int[]{MOCK_UID1});
addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET});
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1});
+ mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID1});
}
@Test
@@ -683,8 +690,8 @@ public class PermissionMonitorTest {
final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService);
addPackage(MOCK_PACKAGE1, MOCK_UID1, new String[] {INTERNET, UPDATE_DEVICE_STATS});
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET
- | INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
+ mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET
+ | PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
// Mock another package with the same uid but different permissions.
final PackageInfo packageInfo2 = buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1);
@@ -695,7 +702,7 @@ public class PermissionMonitorTest {
addPermissions(MOCK_UID1, INTERNET);
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1);
- mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1});
+ mNetdServiceMonitor.expectPermission(PERMISSION_INTERNET, new int[]{MOCK_UID1});
}
@Test
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index de1c5759ee87..e8c4ee9c628d 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -270,12 +270,12 @@ public class VpnTest {
}
@Test
- public void testUidWhiteAndBlacklist() throws Exception {
+ public void testUidAllowAndDenylist() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
final UidRange user = UidRange.createForUser(primaryUser.id);
final String[] packages = {PKGS[0], PKGS[1], PKGS[2]};
- // Whitelist
+ // Allowed list
final Set<UidRange> allow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
Arrays.asList(packages), null);
assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
@@ -283,7 +283,7 @@ public class VpnTest {
new UidRange(user.start + PKG_UIDS[1], user.start + PKG_UIDS[2])
})), allow);
- // Blacklist
+ // Denied list
final Set<UidRange> disallow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
null, Arrays.asList(packages));
assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
@@ -354,11 +354,11 @@ public class VpnTest {
}
@Test
- public void testLockdownWhitelist() throws Exception {
+ public void testLockdownAllowlist() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
final UidRange user = UidRange.createForUser(primaryUser.id);
- // Set always-on with lockdown and whitelist app PKGS[2] from lockdown.
+ // Set always-on with lockdown and allow app PKGS[2] from lockdown.
assertTrue(vpn.setAlwaysOnPackage(
PKGS[1], true, Collections.singletonList(PKGS[2]), mKeyStore));
verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
@@ -368,7 +368,7 @@ public class VpnTest {
assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]);
assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
- // Change whitelisted app to PKGS[3].
+ // Change allowed app list to PKGS[3].
assertTrue(vpn.setAlwaysOnPackage(
PKGS[1], true, Collections.singletonList(PKGS[3]), mKeyStore));
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
@@ -395,7 +395,7 @@ public class VpnTest {
assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]);
- // Remove the whitelist.
+ // Remove the list of allowed packages.
assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null, mKeyStore));
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1),
@@ -408,7 +408,7 @@ public class VpnTest {
user.start + PKG_UIDS[3]);
assertUnblocked(vpn, user.start + PKG_UIDS[0]);
- // Add the whitelist.
+ // Add the list of allowed packages.
assertTrue(vpn.setAlwaysOnPackage(
PKGS[0], true, Collections.singletonList(PKGS[1]), mKeyStore));
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
@@ -421,12 +421,12 @@ public class VpnTest {
assertBlocked(vpn, user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1]);
- // Try whitelisting a package with a comma, should be rejected.
+ // Try allowing a package with a comma, should be rejected.
assertFalse(vpn.setAlwaysOnPackage(
PKGS[0], true, Collections.singletonList("a.b,c.d"), mKeyStore));
- // Pass a non-existent packages in the whitelist, they (and only they) should be ignored.
- // Whitelisted package should change from PGKS[1] to PKGS[2].
+ // Pass a non-existent packages in the allowlist, they (and only they) should be ignored.
+ // allowed package should change from PGKS[1] to PKGS[2].
assertTrue(vpn.setAlwaysOnPackage(
PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"), mKeyStore));
verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[]{
diff --git a/tools/protologtool/Android.bp b/tools/protologtool/Android.bp
index ce551bd0cc10..0be80d31990a 100644
--- a/tools/protologtool/Android.bp
+++ b/tools/protologtool/Android.bp
@@ -2,9 +2,9 @@ java_library_host {
name: "protologtool-lib",
srcs: [
"src/com/android/protolog/tool/**/*.kt",
+ ":protolog-common-src",
],
static_libs: [
- "protolog-common",
"javaparser",
"platformprotos",
"jsonlib",
diff --git a/tools/protologtool/src/com/android/protolog/tool/LogParser.kt b/tools/protologtool/src/com/android/protolog/tool/LogParser.kt
index a59038fc99a0..645c5672da64 100644
--- a/tools/protologtool/src/com/android/protolog/tool/LogParser.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/LogParser.kt
@@ -16,16 +16,15 @@
package com.android.protolog.tool
+import com.android.internal.protolog.ProtoLogFileProto
+import com.android.internal.protolog.ProtoLogMessage
+import com.android.internal.protolog.common.InvalidFormatStringException
+import com.android.internal.protolog.common.LogDataType
import com.android.json.stream.JsonReader
-import com.android.server.protolog.common.InvalidFormatStringException
-import com.android.server.protolog.common.LogDataType
-import com.android.server.protolog.ProtoLogMessage
-import com.android.server.protolog.ProtoLogFileProto
import java.io.BufferedReader
import java.io.InputStream
import java.io.InputStreamReader
import java.io.PrintStream
-import java.lang.Exception
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogGroupReader.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogGroupReader.kt
index 75493b6427cb..42b628b0e262 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogGroupReader.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogGroupReader.kt
@@ -17,7 +17,7 @@
package com.android.protolog.tool
import com.android.protolog.tool.Constants.ENUM_VALUES_METHOD
-import com.android.server.protolog.common.IProtoLogGroup
+import com.android.internal.protolog.common.IProtoLogGroup
import java.io.File
import java.net.URLClassLoader
diff --git a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
index 36ea41129450..27e61a139451 100644
--- a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
@@ -16,7 +16,7 @@
package com.android.protolog.tool
-import com.android.server.protolog.common.LogDataType
+import com.android.internal.protolog.common.LogDataType
import com.github.javaparser.StaticJavaParser
import com.github.javaparser.ast.CompilationUnit
import com.github.javaparser.ast.NodeList
@@ -89,7 +89,7 @@ class SourceTransformer(
// Out: ProtoLog.e(GROUP, 1234, 0, null, arg)
newCall.arguments.add(2, IntegerLiteralExpr(typeMask))
// Replace call to a stub method with an actual implementation.
- // Out: com.android.server.protolog.ProtoLogImpl.e(GROUP, 1234, null, arg)
+ // Out: ProtoLogImpl.e(GROUP, 1234, null, arg)
newCall.setScope(protoLogImplClassNode)
// Create a call to ProtoLog$Cache.GROUP_enabled
// Out: com.android.server.protolog.ProtoLog$Cache.GROUP_enabled
@@ -119,9 +119,9 @@ class SourceTransformer(
}
blockStmt.addStatement(ExpressionStmt(newCall))
// Create an IF-statement with the previously created condition.
- // Out: if (com.android.server.protolog.ProtoLogImpl.isEnabled(GROUP)) {
+ // Out: if (ProtoLogImpl.isEnabled(GROUP)) {
// long protoLogParam0 = arg;
- // com.android.server.protolog.ProtoLogImpl.e(GROUP, 1234, 0, null, protoLogParam0);
+ // ProtoLogImpl.e(GROUP, 1234, 0, null, protoLogParam0);
// }
ifStmt = IfStmt(isLogEnabled, blockStmt, null)
} else {
diff --git a/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt b/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt
index cf36651c3e39..3cfbb435a764 100644
--- a/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt
+++ b/tools/protologtool/tests/com/android/protolog/tool/CommandOptionsTest.kt
@@ -31,7 +31,7 @@ class CommandOptionsTest {
private const val TEST_PROTOLOG_CLASS = "com.android.server.wm.ProtoLog"
private const val TEST_PROTOLOGIMPL_CLASS = "com.android.server.wm.ProtoLogImpl"
private const val TEST_PROTOLOGCACHE_CLASS = "com.android.server.wm.ProtoLog\$Cache"
- private const val TEST_PROTOLOGGROUP_CLASS = "com.android.server.wm.ProtoLogGroup"
+ private const val TEST_PROTOLOGGROUP_CLASS = "com.android.internal.protolog.ProtoLogGroup"
private const val TEST_PROTOLOGGROUP_JAR = "out/soong/.intermediates/frameworks/base/" +
"services/core/services.core.wm.protologgroups/android_common/javac/" +
"services.core.wm.protologgroups.jar"
diff --git a/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt b/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt
index dd8a0b1c50b4..0d2b91d6cfb8 100644
--- a/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt
+++ b/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt
@@ -33,8 +33,8 @@ class EndToEndTest {
val output = run(
src = "frameworks/base/org/example/Example.java" to """
package org.example;
- import com.android.server.protolog.common.ProtoLog;
- import static com.android.server.wm.ProtoLogGroup.GROUP;
+ import com.android.internal.protolog.common.ProtoLog;
+ import static com.android.internal.protolog.ProtoLogGroup.GROUP;
class Example {
void method() {
@@ -46,11 +46,11 @@ class EndToEndTest {
""".trimIndent(),
logGroup = LogGroup("GROUP", true, false, "TAG_GROUP"),
commandOptions = CommandOptions(arrayOf("transform-protolog-calls",
- "--protolog-class", "com.android.server.protolog.common.ProtoLog",
- "--protolog-impl-class", "com.android.server.protolog.ProtoLogImpl",
+ "--protolog-class", "com.android.internal.protolog.common.ProtoLog",
+ "--protolog-impl-class", "com.android.internal.protolog.ProtoLogImpl",
"--protolog-cache-class",
- "com.android.server.protolog.ProtoLog${"\$\$"}Cache",
- "--loggroups-class", "com.android.server.wm.ProtoLogGroup",
+ "com.android.server.wm.ProtoLogCache",
+ "--loggroups-class", "com.android.internal.protolog.ProtoLogGroup",
"--loggroups-jar", "not_required.jar",
"--output-srcjar", "out.srcjar",
"frameworks/base/org/example/Example.java"))
@@ -64,8 +64,8 @@ class EndToEndTest {
val output = run(
src = "frameworks/base/org/example/Example.java" to """
package org.example;
- import com.android.server.protolog.common.ProtoLog;
- import static com.android.server.wm.ProtoLogGroup.GROUP;
+ import com.android.internal.protolog.common.ProtoLog;
+ import static com.android.internal.protolog.ProtoLogGroup.GROUP;
class Example {
void method() {
@@ -77,8 +77,8 @@ class EndToEndTest {
""".trimIndent(),
logGroup = LogGroup("GROUP", true, false, "TAG_GROUP"),
commandOptions = CommandOptions(arrayOf("generate-viewer-config",
- "--protolog-class", "com.android.server.protolog.common.ProtoLog",
- "--loggroups-class", "com.android.server.wm.ProtoLogGroup",
+ "--protolog-class", "com.android.internal.protolog.common.ProtoLog",
+ "--loggroups-class", "com.android.internal.protolog.ProtoLogGroup",
"--loggroups-jar", "not_required.jar",
"--viewer-conf", "out.json",
"frameworks/base/org/example/Example.java"))
diff --git a/tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt b/tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt
index 04a3bfa499d8..67a31da87081 100644
--- a/tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt
+++ b/tools/protologtool/tests/com/android/protolog/tool/LogParserTest.kt
@@ -17,8 +17,8 @@
package com.android.protolog.tool
import com.android.json.stream.JsonReader
-import com.android.server.protolog.ProtoLogMessage
-import com.android.server.protolog.ProtoLogFileProto
+import com.android.internal.protolog.ProtoLogMessage
+import com.android.internal.protolog.ProtoLogFileProto
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt
index 53c69c47d052..eff64a31367a 100644
--- a/wifi/api/system-current.txt
+++ b/wifi/api/system-current.txt
@@ -326,6 +326,8 @@ package android.net.wifi {
field @Deprecated public static final int METERED_OVERRIDE_METERED = 1; // 0x1
field @Deprecated public static final int METERED_OVERRIDE_NONE = 0; // 0x0
field @Deprecated public static final int METERED_OVERRIDE_NOT_METERED = 2; // 0x2
+ field @Deprecated public static final int RANDOMIZATION_AUTO = 3; // 0x3
+ field @Deprecated public static final int RANDOMIZATION_ENHANCED = 2; // 0x2
field @Deprecated public static final int RANDOMIZATION_NONE = 0; // 0x0
field @Deprecated public static final int RANDOMIZATION_PERSISTENT = 1; // 0x1
field @Deprecated public static final int RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA = 17; // 0x11
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 71f0ab8087ab..1588bf72c969 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1130,7 +1130,9 @@ public class WifiConfiguration implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"RANDOMIZATION_"}, value = {
RANDOMIZATION_NONE,
- RANDOMIZATION_PERSISTENT})
+ RANDOMIZATION_PERSISTENT,
+ RANDOMIZATION_ENHANCED,
+ RANDOMIZATION_AUTO})
public @interface MacRandomizationSetting {}
/**
@@ -1147,14 +1149,30 @@ public class WifiConfiguration implements Parcelable {
public static final int RANDOMIZATION_PERSISTENT = 1;
/**
+ * Use a randomly generated MAC address for connections to this network.
+ * This option does not persist the randomized MAC address.
+ * @hide
+ */
+ @SystemApi
+ public static final int RANDOMIZATION_ENHANCED = 2;
+
+ /**
+ * Let the wifi framework automatically decide the MAC randomization strategy.
+ * @hide
+ */
+ @SystemApi
+ public static final int RANDOMIZATION_AUTO = 3;
+
+ /**
* Level of MAC randomization for this network.
- * One of {@link #RANDOMIZATION_NONE} or {@link #RANDOMIZATION_PERSISTENT}.
- * By default this field is set to {@link #RANDOMIZATION_PERSISTENT}.
+ * One of {@link #RANDOMIZATION_NONE}, {@link #RANDOMIZATION_AUTO},
+ * {@link #RANDOMIZATION_PERSISTENT} or {@link #RANDOMIZATION_ENHANCED}.
+ * By default this field is set to {@link #RANDOMIZATION_AUTO}.
* @hide
*/
@SystemApi
@MacRandomizationSetting
- public int macRandomizationSetting = RANDOMIZATION_PERSISTENT;
+ public int macRandomizationSetting = RANDOMIZATION_AUTO;
/**
* @hide
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index fa806e7797cd..282757ac5a14 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -448,6 +448,16 @@ public final class Credential implements Parcelable {
return new UserCredential[size];
}
};
+
+ /**
+ * Get a unique identifier for UserCredential.
+ *
+ * @hide
+ * @return a Unique identifier for a UserCredential object
+ */
+ public int getUniqueId() {
+ return Objects.hash(mUsername);
+ }
}
private UserCredential mUserCredential = null;
/**
@@ -1037,7 +1047,8 @@ public final class Credential implements Parcelable {
* @return a Unique identifier for a Credential object
*/
public int getUniqueId() {
- return Objects.hash(mUserCredential, mCertCredential, mSimCredential, mRealm);
+ return Objects.hash(mUserCredential != null ? mUserCredential.getUniqueId() : 0,
+ mCertCredential, mSimCredential, mRealm);
}
@Override
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
index 224c4bed9d5b..8f34579f6a5d 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
@@ -313,9 +313,7 @@ public final class HomeSp implements Parcelable {
* @return a Unique identifier for a HomeSp object
*/
public int getUniqueId() {
- return Objects.hash(mFqdn, mFriendlyName, mHomeNetworkIds, Arrays.hashCode(mMatchAllOis),
- Arrays.hashCode(mMatchAnyOis), Arrays.hashCode(mOtherHomePartners),
- Arrays.hashCode(mRoamingConsortiumOis));
+ return Objects.hash(mFqdn);
}
diff --git a/wifi/tests/src/android/net/wifi/FakeKeys.java b/wifi/tests/src/android/net/wifi/FakeKeys.java
index c0d60c33f99c..641b891a1f4d 100644
--- a/wifi/tests/src/android/net/wifi/FakeKeys.java
+++ b/wifi/tests/src/android/net/wifi/FakeKeys.java
@@ -214,6 +214,35 @@ public class FakeKeys {
};
public static final PrivateKey RSA_KEY1 = loadPrivateRSAKey(FAKE_RSA_KEY_1);
+ private static final String CLIENT_SUITE_B_RSA3072_CERT_STRING =
+ "-----BEGIN CERTIFICATE-----\n"
+ + "MIIERzCCAq8CFDopjyNgaj+c2TN2k06h7okEWpHJMA0GCSqGSIb3DQEBDAUAMF4x\n"
+ + "CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDTVRWMRAwDgYDVQQK\n"
+ + "DAdBbmRyb2lkMQ4wDAYDVQQLDAVXaS1GaTESMBAGA1UEAwwJdW5pdGVzdENBMB4X\n"
+ + "DTIwMDcyMTAyMjkxMVoXDTMwMDUzMDAyMjkxMVowYjELMAkGA1UEBhMCVVMxCzAJ\n"
+ + "BgNVBAgMAkNBMQwwCgYDVQQHDANNVFYxEDAOBgNVBAoMB0FuZHJvaWQxDjAMBgNV\n"
+ + "BAsMBVdpLUZpMRYwFAYDVQQDDA11bml0ZXN0Q2xpZW50MIIBojANBgkqhkiG9w0B\n"
+ + "AQEFAAOCAY8AMIIBigKCAYEAwSK3C5K5udtCKTnE14e8z2cZvwmB4Xe+a8+7QLud\n"
+ + "Hooc/lQzClgK4MbVUC0D3FE+U32C78SxKoTaRWtvPmNm+UaFT8KkwyUno/dv+2XD\n"
+ + "pd/zARQ+3FwAfWopAhEyCVSxwsCa+slQ4juRIMIuUC1Mm0NaptZyM3Tj/ICQEfpk\n"
+ + "o9qVIbiK6eoJMTkY8EWfAn7RTFdfR1OLuO0mVOjgLW9/+upYv6hZ19nAMAxw4QTJ\n"
+ + "x7lLwALX7B+tDYNEZHDqYL2zyvQWAj2HClere8QYILxkvktgBg2crEJJe4XbDH7L\n"
+ + "A3rrXmsiqf1ZbfFFEzK9NFqovL+qGh+zIP+588ShJFO9H/RDnDpiTnAFTWXQdTwg\n"
+ + "szSS0Vw2PB+JqEABAa9DeMvXT1Oy+NY3ItPHyy63nQZVI2rXANw4NhwS0Z6DF+Qs\n"
+ + "TNrj+GU7e4SG/EGR8SvldjYfQTWFLg1l/UT1hOOkQZwdsaW1zgKyeuiFB2KdMmbA\n"
+ + "Sq+Ux1L1KICo0IglwWcB/8nnAgMBAAEwDQYJKoZIhvcNAQEMBQADggGBAMYwJkNw\n"
+ + "BaCviKFmReDTMwWPRy4AMNViEeqAXgERwDEKwM7efjsaj5gctWfKsxX6UdLzkhgg\n"
+ + "6S/T6PxVWKzJ6l7SoOuTa6tMQOZp+h3R1mdfEQbw8B5cXBxZ+batzAai6Fiy1FKS\n"
+ + "/ka3INbcGfYuIYghfTrb4/NJKN06ZaQ1bpPwq0e4gN7800T2nbawvSf7r+8ZLcG3\n"
+ + "6bGCjRMwDSIipNvOwoj3TG315XC7TccX5difQ4sKOY+d2MkVJ3RiO0Ciw2ZbEW8d\n"
+ + "1FH5vUQJWnBUfSFznosGzLwH3iWfqlP+27jNE+qB2igEwCRFgVAouURx5ou43xuX\n"
+ + "qf6JkdI3HTJGLIWxkp7gOeln4dEaYzKjYw+P0VqJvKVqQ0IXiLjHgE0J9p0vgyD6\n"
+ + "HVVcP7U8RgqrbIjL1QgHU4KBhGi+WSUh/mRplUCNvHgcYdcHi/gHpj/j6ubwqIGV\n"
+ + "z4iSolAHYTmBWcLyE0NgpzE6ntp+53r2KaUJA99l2iGVzbWTwqPSm0XAVw==\n"
+ + "-----END CERTIFICATE-----\n";
+ public static final X509Certificate CLIENT_SUITE_B_RSA3072_CERT =
+ loadCertificate(CLIENT_SUITE_B_RSA3072_CERT_STRING);
+
private static X509Certificate loadCertificate(String blob) {
try {
final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 638efb9f14ee..8270d643ca65 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -23,6 +23,8 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
+import android.net.wifi.EAPConstants;
+import android.net.wifi.FakeKeys;
import android.net.wifi.hotspot2.pps.Credential;
import android.net.wifi.hotspot2.pps.HomeSp;
import android.os.Parcel;
@@ -32,6 +34,11 @@ import androidx.test.filters.SmallTest;
import org.junit.Test;
import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -383,19 +390,39 @@ public class PasspointConfigurationTest {
}
/**
- * Verify that the unique identifier generated is different for two instances with different
- * HomeSp node
+ * Verify that the unique identifier generated is the same for two instances with different
+ * HomeSp node but same FQDN
*
* @throws Exception
*/
@Test
- public void validateUniqueIdDifferentHomeSp() throws Exception {
+ public void validateUniqueIdDifferentHomeSpSameFqdn() throws Exception {
PasspointConfiguration config1 = PasspointTestUtils.createConfig();
- // Modify config2's RCOIs to a different set of values
+ // Modify config2's RCOIs and friendly name to a different set of values
PasspointConfiguration config2 = PasspointTestUtils.createConfig();
HomeSp homeSp = config2.getHomeSp();
homeSp.setRoamingConsortiumOis(new long[] {0xaa, 0xbb});
+ homeSp.setFriendlyName("Some other name");
+ config2.setHomeSp(homeSp);
+
+ assertEquals(config1.getUniqueId(), config2.getUniqueId());
+ }
+
+ /**
+ * Verify that the unique identifier generated is different for two instances with the same
+ * HomeSp node but different FQDN
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateUniqueIdSameHomeSpDifferentFqdn() throws Exception {
+ PasspointConfiguration config1 = PasspointTestUtils.createConfig();
+
+ // Modify config2's FQDN to a different value
+ PasspointConfiguration config2 = PasspointTestUtils.createConfig();
+ HomeSp homeSp = config2.getHomeSp();
+ homeSp.setFqdn("fqdn2.com");
config2.setHomeSp(homeSp);
assertNotEquals(config1.getUniqueId(), config2.getUniqueId());
@@ -403,15 +430,15 @@ public class PasspointConfigurationTest {
/**
* Verify that the unique identifier generated is different for two instances with different
- * Credential node
+ * SIM Credential node
*
* @throws Exception
*/
@Test
- public void validateUniqueIdDifferentCredential() throws Exception {
+ public void validateUniqueIdDifferentSimCredential() throws Exception {
PasspointConfiguration config1 = PasspointTestUtils.createConfig();
- // Modify config2's RCOIs to a different set of values
+ // Modify config2's realm and SIM credential to a different set of values
PasspointConfiguration config2 = PasspointTestUtils.createConfig();
Credential credential = config2.getCredential();
credential.setRealm("realm2.example.com");
@@ -422,6 +449,157 @@ public class PasspointConfigurationTest {
}
/**
+ * Verify that the unique identifier generated is different for two instances with different
+ * Realm in the Credential node
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateUniqueIdDifferentRealm() throws Exception {
+ PasspointConfiguration config1 = PasspointTestUtils.createConfig();
+
+ // Modify config2's realm to a different set of values
+ PasspointConfiguration config2 = PasspointTestUtils.createConfig();
+ Credential credential = config2.getCredential();
+ credential.setRealm("realm2.example.com");
+ config2.setCredential(credential);
+
+ assertNotEquals(config1.getUniqueId(), config2.getUniqueId());
+ }
+
+ /**
+ * Verify that the unique identifier generated is the same for two instances with different
+ * password and same username in the User Credential node
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateUniqueIdSameUserInUserCredential() throws Exception {
+ PasspointConfiguration config1 = PasspointTestUtils.createConfig();
+ Credential credential = createCredentialWithUserCredential("user", "passwd");
+ config1.setCredential(credential);
+
+ // Modify config2's Passpowrd to a different set of values
+ PasspointConfiguration config2 = PasspointTestUtils.createConfig();
+ credential = createCredentialWithUserCredential("user", "newpasswd");
+ config2.setCredential(credential);
+
+ assertEquals(config1.getUniqueId(), config2.getUniqueId());
+ }
+
+ /**
+ * Verify that the unique identifier generated is different for two instances with different
+ * username in the User Credential node
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateUniqueIdDifferentUserCredential() throws Exception {
+ PasspointConfiguration config1 = PasspointTestUtils.createConfig();
+ Credential credential = createCredentialWithUserCredential("user", "passwd");
+ config1.setCredential(credential);
+
+ // Modify config2's username to a different value
+ PasspointConfiguration config2 = PasspointTestUtils.createConfig();
+ credential = createCredentialWithUserCredential("user2", "passwd");
+ config2.setCredential(credential);
+
+ assertNotEquals(config1.getUniqueId(), config2.getUniqueId());
+ }
+
+ /**
+ * Verify that the unique identifier generated is different for two instances with different
+ * Cert Credential node
+ *
+ * @throws Exception
+ */
+ @Test
+ public void validateUniqueIdDifferentCertCredential() throws Exception {
+ PasspointConfiguration config1 = PasspointTestUtils.createConfig();
+ Credential credential = createCredentialWithCertificateCredential(true, true);
+ config1.setCredential(credential);
+
+ // Modify config2's cert credential to a different set of values
+ PasspointConfiguration config2 = PasspointTestUtils.createConfig();
+ credential = createCredentialWithCertificateCredential(false, false);
+ config2.setCredential(credential);
+
+ assertNotEquals(config1.getUniqueId(), config2.getUniqueId());
+ }
+
+ /**
+ * Helper function for generating certificate credential for testing.
+ *
+ * @return {@link Credential}
+ */
+ private static Credential createCredentialWithCertificateCredential(Boolean useCaCert0,
+ Boolean useCert0)
+ throws NoSuchAlgorithmException, CertificateEncodingException {
+ Credential.CertificateCredential certCred = new Credential.CertificateCredential();
+ certCred.setCertType("x509v3");
+ if (useCert0) {
+ certCred.setCertSha256Fingerprint(
+ MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded()));
+ } else {
+ certCred.setCertSha256Fingerprint(MessageDigest.getInstance("SHA-256")
+ .digest(FakeKeys.CLIENT_SUITE_B_RSA3072_CERT.getEncoded()));
+ }
+ return createCredential(null, certCred, null, new X509Certificate[] {FakeKeys.CLIENT_CERT},
+ FakeKeys.RSA_KEY1, useCaCert0 ? FakeKeys.CA_CERT0 : FakeKeys.CA_CERT1);
+ }
+
+ /**
+ * Helper function for generating user credential for testing.
+ *
+ * @return {@link Credential}
+ */
+ private static Credential createCredentialWithUserCredential(String username, String password) {
+ Credential.UserCredential userCred = new Credential.UserCredential();
+ userCred.setUsername(username);
+ userCred.setPassword(password);
+ userCred.setMachineManaged(true);
+ userCred.setAbleToShare(true);
+ userCred.setSoftTokenApp("TestApp");
+ userCred.setEapType(EAPConstants.EAP_TTLS);
+ userCred.setNonEapInnerMethod("MS-CHAP");
+ return createCredential(userCred, null, null, null, null, FakeKeys.CA_CERT0);
+ }
+
+ /**
+ * Helper function for generating Credential for testing.
+ *
+ * @param userCred Instance of UserCredential
+ * @param certCred Instance of CertificateCredential
+ * @param simCred Instance of SimCredential
+ * @param clientCertificateChain Chain of client certificates
+ * @param clientPrivateKey Client private key
+ * @param caCerts CA certificates
+ * @return {@link Credential}
+ */
+ private static Credential createCredential(Credential.UserCredential userCred,
+ Credential.CertificateCredential certCred,
+ Credential.SimCredential simCred,
+ X509Certificate[] clientCertificateChain, PrivateKey clientPrivateKey,
+ X509Certificate... caCerts) {
+ Credential cred = new Credential();
+ cred.setCreationTimeInMillis(123455L);
+ cred.setExpirationTimeInMillis(2310093L);
+ cred.setRealm("realm");
+ cred.setCheckAaaServerCertStatus(true);
+ cred.setUserCredential(userCred);
+ cred.setCertCredential(certCred);
+ cred.setSimCredential(simCred);
+ if (caCerts != null && caCerts.length == 1) {
+ cred.setCaCertificate(caCerts[0]);
+ } else {
+ cred.setCaCertificates(caCerts);
+ }
+ cred.setClientCertificateChain(clientCertificateChain);
+ cred.setClientPrivateKey(clientPrivateKey);
+ return cred;
+ }
+
+ /**
* Verify that the unique identifier API generates an exception if HomeSP is not initialized.
*
* @throws Exception
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
index 829d8f0a9a3a..a44df40a8e97 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
@@ -593,10 +593,10 @@ public class CredentialTest {
}
/**
- * Verify that unique identifiers are different for a credential with different values
+ * Verify that unique identifiers are different for a credential with different username
*/
@Test
- public void testUniqueIdDifferentForUserCredentialsWithDifferentValues() throws Exception {
+ public void testUniqueIdDifferentForUserCredentialsWithDifferentUsername() throws Exception {
Credential userCred1 = createCredentialWithUserCredential();
Credential userCred2 = createCredentialWithUserCredential();
userCred2.getUserCredential().setUsername("anotheruser");
@@ -605,7 +605,24 @@ public class CredentialTest {
}
/**
- * Verify that unique identifiers are different for a credential with different values
+ * Verify that unique identifiers are different for a credential with different password and
+ * other values other than username
+ */
+ @Test
+ public void testUniqueIdSameForUserCredentialsWithDifferentPassword() throws Exception {
+ Credential userCred1 = createCredentialWithUserCredential();
+ Credential userCred2 = createCredentialWithUserCredential();
+ userCred2.getUserCredential().setPassword("someotherpassword!");
+ userCred2.getUserCredential().setMachineManaged(false);
+ userCred2.getUserCredential().setAbleToShare(false);
+ userCred2.getUserCredential().setSoftTokenApp("TestApp2");
+ userCred2.getUserCredential().setNonEapInnerMethod("PAP");
+
+ assertEquals(userCred1.getUniqueId(), userCred2.getUniqueId());
+ }
+
+ /**
+ * Verify that unique identifiers are different for a cert credential with different values
*/
@Test
public void testUniqueIdDifferentForCertCredentialsWithDifferentValues() throws Exception {